Puppeteer设置浏览器代理的三种思路

目录
  1. 1. 背景
  2. 2. 1 通过启动参数设置代理
  3. 3. 2 通过代理服务器控制代理逻辑
  4. 4. 3 通过拦截器与第三方库实现设置代理功能
  5. 5. 4 总结
  6. 6. 5 参考资料

背景

Puppeteer是google推出的操作浏览器的框架。当我们通过框架操作浏览器去访问页面通常需要设置代理。本文简要总结设置代理的方式。

1 通过启动参数设置代理

我们通过puppeteer启动浏览通常可以指定参数,通过–proxy-server参数[1]指定代理。http及https请求的将通过代理服务器访问。若每次需要更换代理就需要重新通过launch方法来启动浏览器。

1
2
3
4
5
6
7
8
9
10
11
12
13
const browser = await puppeteer.launch({
args: [
'--disable-setuid-sandbox',
'--no-sandbox',
'--proxy-server=10.24.51.125:8411',
'--ignore-certificate-errors',
'--window-size=375,812',
'--remote-debugging-port=9222'
],
ignoreHTTPSErrors: true,
headless: false,
executablePath: "/chrome-mac/Chromium.app/Contents/MacOS/Chromium",
});

这种方式启动后,默认会有一个打开的page,因此不用再重新打开page对象。用默认的page进行后续访问即可。

1
const [page] = await browser.pages();

2 通过代理服务器控制代理逻辑

可以看到–proxy-server设置了代理后,如果ip是一个固定的目标代理地址那么需要重新启动浏览器才能更换。如果我们自己开发了一个代理服务,与实际代理机器交互的逻辑都集中在这个服务上,那么实际代理机器的访问通过我们的代理服务控制,这样我们每次启动浏览器后就固定一个地址即可。

3 通过拦截器与第三方库实现设置代理功能

1中介绍的方式需要每次重新调用launch方法启动浏览器更换IP。但我们知道现在很多http库都可以设置代理。例如在Java中可以通过okhttp,unirest等库来设置代理。同理nodejs中也有这样的库。我们不再通过–proxy-server指定地址,而是通过puppeteer的拦截器功能,将请求拦截,随后改写请求。再通过第三方的http库设置上代理信息。这样就可以达到不通过launch重启浏览器而是直接在一个page中设置代理的目的。每次有新请求来了也可以达到动态变化的目标。不过这样处理逻辑还是比较复杂,涉及改写请求,响应结果缓存处理等问题。这篇讨论[2]已经给出了处理方式,可以参考。

4 总结

如果在上规模的系统中代理控制一般统一由统一的代理服务来管理,使用时通过proy-server指定代理信息即可。如果是小规模系统,都是集中式控制可以考虑使用1,3的方式处理。

5 参考资料

[1]chrome命令行参数,https://peter.sh/experiments/chromium-command-line-switches/
[2]代理设置的几种方法讨论, https://github.com/GoogleChrome/puppeteer/issues/678


扩展组件puppeteer-page-proxy可以实现page或者request级别的代理,而不用每次都要重启浏览器。
经测试,爬取携程数据的时候,会报错TypeError: Cannot read property 'url' of null,解决方法:
In case of any CORS errors, use --disable-web-security launch flag:

1
2
3
const browser = await puppeteer.launch({
args: ['--disable-web-security']
});

使用这个插件的时候要慎重,实际使用的时候,会频繁出现网络请求超时的情况,不知道是不是因为请求是HTTPS的缘故。