puppeteer爬虫快速上手

183 阅读3分钟

puppeteer 是什么?

点进这篇文章的你,相信已经知道 puppeteer 是什么东西了,如果你不知道,在这里我简单的介绍一下:

  • puppeteer 是一个操作浏览器的工具包
  • 常见的就两个用途:爬虫、端到端测试。除此之外做SSR同构渲染也可能会用到。

其他平台也有类似的软件,比如支持 python、java、.Net 的 playwright。这种工具一般叫做 RPA,也就是计算机自动化辅助工具。

puppeteer 等工具,支持最好的是 chromium(或者说 chrome)

这篇文章主要说爬虫,或者换个说法,我如何去控制浏览器,拿到网页中的元素、控制网页做事?

下面我以 puppeteer 和 chrome 为例说明,其他的可以参照文档,playwright 的 API 和 puppeteer 差不多

速查表

要想控制浏览器,首先和浏览器要建立连接关系,

  • 可以使用 puppeteer.connect 连接一个已经启动的 chrome
  • 也可以使用 puppeteer.launch 启动新的 chrome 实例,各种启动参数都可以指定

这两个方法的返回值都是浏览器 browser 实例,获取到实例后可以控制打开想要爬取的页面

打开爬取页面分两步

  1. 使用 browser.newPage打开新的标签页,或者在 browser.pages 数组中找到并复用已经打开的标签页
  2. 使用 page.goto(url) 跳转到想要打开的地址

什么时候页面加载完成了呢?执行 wait 开头的方法,等就行了

有这些比较常用的方法:

方法描述
page.waitForTimeout等待你指定的一段时间
page.waitForFunction执行一个方法,等待方法返回真值
page.waitForSelector使用 selector 查找元素,等待出现
page.waitForXPath使用 xpath 查找元素,等待元素出现

等页面加载完了,或者等你想要的内容出来了,或者是我就想等10s,完成了就可以操作了

那如何操作页面做事?

  1. 可以通过 page.exposeFunction 将方法注入到浏览器,甚至可以暴露 node 内部的方法给浏览器端执行。

比如说我想将日志传递到node记录,

就可以在控制端执行暴露方法

page.exposeFunction('$log', (...args) => winLogger.info(...args))

在被控端就能在全局window中拿到这个方法执行

$log('hello world')
  1. 可以在 node 端调用 page.evaluate,调用浏览器内的方法、获取浏览器端全局作用域里的变量

比如说浏览器 window 对象有个方法

window.someFunction = (a) => doSomething(a)

在node端调用就可以

await page.evaluate((a) => {
    window.someFunction(a)
}, {a: somedata})

evaluate 方法第一个参数是执行函数,第二个参数是需要传入函数的值

执行阶段可能遇到的问题

  1. 大小

puppeteer 和 chrome 之间通过 cdp 协议通信,默认是 websocket,受到默认 websocket 配置参数的限制,超过80M左右的大数据没法传输到浏览器。

什么时候会传递数据呢?比如说 page.evaluate 方法第二个参数传递值

怎么办?大数据量分片传递,或者使用其他方法,比如将大数据写入本地文件或放到oss,在浏览器端调用读文件方法或者从oss拉取,绕过直接传递通信

  1. 只能传递可序列化的值

object 和 function 是没法传递的,如果你想传递 function,可以转换成 string 传递,然后在内部使用 new Function 转换成函数

下一步

我写完这个速查表之后,才发现站里有个四年前的文章写得很全了。刚入门推荐看这个,能知道边界在哪里 # 结合项目来谈谈 Puppeteer