抓取动态网页(Node.js里的爬取动态网页神器Puppeteer的好处和坏处)
优采云 发布时间: 2021-09-13 01:15抓取动态网页(Node.js里的爬取动态网页神器Puppeteer的好处和坏处)
目前的网页大多是动态网页。如果单纯爬取网页的HTML文件,就无法爬取到商品价格或者后期需要加载的图片等重要信息,更别提那些疯狂的登录限制了,对于小型爬虫来说,换句话说就是分析那些复杂的脚本不值得损失,更何况网站会与时俱进,而且很难破解。一旦更新,他们必须从头开始。这大大增加了小爬虫的难度。
不过好在Node.js中有这样的神器,不怕网站的登录限制和反爬虫措施。它将保持不变,可以通过简单的模拟用户操作来破解。部分限制在于它是 Puppeteer,一个由 Google 生产的爬行动态网页神器。
1.Puppeteer 的利弊
Puppeteer 本质上是一个 chrome 浏览器,但它可以通过代码进行操作。比如模拟鼠标点击、键盘输入等操作,有点像按钮向导。网页很难区分这是人类用户还是爬虫,因此无处可谈。
它的优点是简单,非常简单,可能是所有可以抓取动态网页的库中最简单的一个。
但是缺点也很明显,就是速度慢,效率有点低。相当于每次运行都启动一个Chrome浏览器,所以效率远不如其他库,不适合抓取大数据。但是对于一个小型爬虫来说已经绰绰有余了。
接下来以我写的爬取jd产品页面的小爬虫为例,看看这个有多么简单。本文章仅供学习交流使用,请勿用于其他用途。
我写这个爬虫是为了买苹果的魔控板。找了之后发*敏*感*词*银岛的价格很诱人。这应该是金银岛唯一值得抢的物品,但数量稀少。 ,要等很久才会出现。
于是想到了监控产品页面,发现新的魔控板会弹出提示。甚至可以实现自动竞价,不过我没写。毕竟除了触控板我不想买。我无法测试它是否可以成功拍摄。
好的,开始吧!
2.Install Puppeteer:
先安装Puppeteer库,只用到这个库:
npm install puppeteer
3.开始链接网页
链接网页也很简单,只需要几行代码:
const puppeteer = require('puppeteer')
//启动浏览器
const browers = await puppeteer.launch()
//启动新页面
const page = await browers.newPage()
//链接网址
await page.goto(url)
这样,链接就成功了! Puppeteer.launch() 也可以接收很多参数,但是这里我们只使用headless,默认为ture,如果为false,则显示浏览器界面。我们可以利用这个功能来实现弹窗提醒,一旦发现有符合条件的产品就将headless改成false。
4.crawl 产品信息
链接网页后,下一步就是抓取产品信息并进行分析。
网址:魔法控制板
4.1 获取对应的元素标签
从页面中可以看出,一旦旁边的同类宝藏中出现类似的商品,我们只需要抓取那里的信息即可。有两种方式:
一个是$eval,相当于js中的document.querySelector,只抓取第一个匹配的元素;
另一个是$$eval,相当于js中的document.querySelectorAll,爬取所有匹配的元素;
他们收到的第一个参数是元素地址,第二个参数是回调函数。操作与 document.querySelector 相同。看代码:
//拿到同类夺宝里的所有子元素
const goods = page.$$eval('#auctionRecommend > div.mc > ul > li', ele => ele)
4.2.分析产品信息
既然我已经拿到了同一种宝贝所有产品的标签信息,我就开始分析信息了。
获取里面所有产品的名称,然后检查关键字是否存在,如果存在,把headless改成false提醒弹窗,如果不存在,半小时后再链接。
Puppeteer 提供了一个等待命令 page.waitFor(),它不仅可以根据时间等待,还可以根据某个元素的加载进度进行等待。
const goods = page.$$eval('#auctionRecommend > div.mc > ul > li', el => {
//错误和关键字不存在都会返回false
try {
for (let i = 0; i {
if(b){
console.log('有货了!')
await page.waitFor(2000)
await browers.close()
return requestUrl(false)
} else {
console.log('还没货')
console.log('三十分钟后再尝试')
await page.waitFor(1800000)
await browers.close()
return requestUrl(true)
}
})
5.优化代码
对于这个小爬虫来说,效率的损失并不多,不需要优化,但作为强迫症,还是希望尽量去除。
5.1块图片
在这个爬虫中,我们根本不需要看任何图片信息,所以不需要加载所有图片。为了稍微提高一点操作效率,所有图片都被屏蔽了:
//开启*敏*感*词*
await page.setRequestInterception(true)
await page.on('request',interceptedRequest => {
//判断加载的url是否以jpg或png结尾,符合条件将不再加载
if(interceptedRequest.url().endsWith('.jpg') || interceptedRequest.url().endsWith('.png')){
interceptedRequest.abort();
}else{
interceptedRequest.continue();
}
})
5.2 调整窗口大小
当浏览器弹出时,你会发现打开的窗口显示范围很小,不仅浏览不方便,还可能导致点击或输入等操作出错,所以还是有必要的调整:
await page.setViewport({
width: 1920,
height: 1080,
})
到此,所有的代码都已经完成了,来试试效果吧!
6.完整代码
const puppeteer = require('puppeteer')
const url = 'https://paipai.jd.com/auction-detail/114533257?entryid=p0120003dbdnavi'
const requestUrl = async function(bool){
const browers = await puppeteer.launch({headless:bool})
const page = await browers.newPage()
await page.setRequestInterception(true)
await page.on('request',interceptedRequest => {
if(interceptedRequest.url().endsWith('.jpg') || interceptedRequest.url().endsWith('.png')){
interceptedRequest.abort();
}else{
interceptedRequest.continue();
}
})
await page.setViewport({
width: 1920,
height: 1080,
})
await page.goto(url)
const goods = page.$$eval('#auctionRecommend > div.mc > ul > li', el=>{
try {
for (let i = 0; i {
if(b){
console.log('有货了!')
await page.waitFor(2000)
await browers.close()
return requestUrl(false)
} else {
console.log('还没货')
console.log('三十分钟后再尝试')
await page.waitFor(1800000)
await browers.close()
return requestUrl(true)
}
})
}
requestUrl(true)
也可以通过Github获取完整代码:watchJd.js
如果对你有帮助,欢迎关注我,我会继续输出更多好的文章!