所需环境
- Chrome 浏览器
因为 puppeteer 是 Chrome 推出的无头浏览器,依赖于 Chrome
- NodeJS 环境
- puppeteer 依赖包
cnpm i puppeteer
爬取前的一点分析
爬取一个东西首先要知道他是如何加载的
-
加载更多按钮
加载更多
这个比较简单 使用 puppeteer 判断 然后模拟点击即可
-
滚动加载
说滚动加载其实并不准确,百度文库的文章,类似于只显示 当前视口的范围 正负多一点。就算前面已经加载过了的内容,当你 将页面的滚动条向下 滚动时,如果离开先前视口的距离过多,那么上面的内容又会隐藏掉。
图示
类似于这张图, 页面显示的内容只有 绿色的区域,随着 红色的区域(视口)的变化,绿色的区域也会变化。
所以这里的思路是,首先打开全部文档(点击加载更多按钮),其次,让滚动条滚动到顶部,然后定时每次向下滚动一定的距离(这样就可以获取当前这一段显示的文档),最后再见获取到的所有DOM结构进行 拼合 去重(获取会有重复的结构)
代码:
const puppeteer = require('puppeteer') // 加载模板
;(async () => {
const browser = await puppeteer.launch({ // 创建 browser 实例
// headless: false
})
const page = await browser.newPage() // 创建 page 实例
await page.goto('https://wenku.baidu.com/view/9ec3d0e0571252d380eb6294dd88d0d233d43ce5.html') // 输入导航的网址(百度文库地址)
console.log('go to https://....')
// 设置 屏幕视口
await page.setViewport({
width: 1024,
height: 600,
deviceScaleFactor: 3
})
if (await page.$('span.moreBtn')) { // 判断是否在加载更多按钮
console.log('click loadMore')
await page.waitForSelector('span.moreBtn')
await page.click('span.moreBtn')
await page.waitFor(4000) // 等待文档加载,可根据网络环境更改 时间
console.log('loading done, Crawling doc...')
}
const result = await page.evaluate(async () => { // 浏览器上下文环境
const $ = window.$ // 获取 jQ
let items = []
for(let i = 0; i < document.body.scrollHeight; i+=1000) { // 滚动加载,每次滚动 1000px
console.log(document.body.scrollHeight)
window.scrollTo(0, i)
await async function sleep() { // 每次滚动后 等待一秒
return new Promise(reject => setTimeout(reject, 1000))
}();
// 拼合数组
items = Array.prototype.concat.apply(items, $('p.reader-word-layer')) // 滚动加载 获取文本
}
// await async function sleep() {
// return new Promise(reject => setTimeout(reject, 1000))
// }();
const list = Array.from(new Set(items)) // 数组去重
let html = ''
for(let i = 0; i < list.length; i++){ // 迭代 获取文本
html += list[i].innerText
}
// 返回获取的文本
return html
})
// 输出
console.log(result)
await browser.close()
})();

对应的文章越长需要等待的时间越久。
如果想更好的看到这个过程,可以将 headless 设置为 false,显示浏览器爬取的过程
// ...
const browser = await puppeteer.launch({ // 创建 browser 实例
headless: false
})
// ...
至此一个简单的爬虫就书写完毕了。
网友评论