如何在不重启已打开的Puppeteer浏览器的前提下动态切换代理?
Puppeteer动态切换代理(无需重启浏览器)
Puppeteer启动时传入的
--proxy-server参数仅在浏览器进程初始化时读取生效,运行时修改对应变量无法触发代理配置更新,因此之前的方案不生效。
方案1:使用puppeteer-page-proxy库(页粒度代理,最简便)
这个库可以针对单个页面独立设置代理,不需要修改浏览器全局配置,切换代理只需重新调用设置方法即可,刷新页面就会生效。
安装依赖
npm install puppeteer-page-proxy
改造后的初始化代码
const useProxy = require('puppeteer-page-proxy'); var proxies = get_proxy() // 原有获取代理逻辑 var useragent = randomUseragent.getRandom() let browser = await puppeteer.launch({ headless: false, args: [ // 可删除原有的--proxy-server启动参数 `--user-agent="${useragent}"`, '--no-sandbox', '--disable-setuid-sandbox', '--disable-infobars', '--window-position=0,0', '--ignore-certifcate-errors', '--ignore-certifcate-errors-spki-list' ] }) let page = await browser.newPage() // 初始化设置第一个代理 await useProxy(page, `http://${proxies.address}:${proxies.port}`)
代理封禁后的切换逻辑
const proxy_banned = await check_proxy_ban() if(proxy_banned){ // 拉取新的代理 const newProxy = get_proxy() // 直接给当前页面设置新代理即可,无需重启浏览器 await useProxy(page, `http://${newProxy.address}:${newProxy.port}`) // 刷新页面自动走新代理 await page.reload() return } else{ return }
如果你的代理需要身份验证,直接在代理地址里加认证信息即可:
await useProxy(page, `http://${username}:${password}@${newProxy.address}:${newProxy.port}`)
方案2:原生CDP实现(轻量化无额外UI依赖)
如果不想引入puppeteer-page-proxy,可以直接调用Chrome DevTools Protocol的Fetch域实现代理转发,核心是拦截所有页面请求,通过新代理发送后再返回给页面,需要先安装http/https代理请求依赖:
npm install http-proxy-agent https-proxy-agent
代理切换封装方法示例:
const HttpProxyAgent = require('http-proxy-agent'); const HttpsProxyAgent = require('https-proxy-agent'); // 切换代理的封装方法 async function setPageProxy(page, proxyHost, proxyPort) { const client = await page.createCDPSession() // 启用Fetch域,拦截所有请求 await client.send('Fetch.enable', { patterns: [{ urlPattern: '*' }] }) // 监听请求拦截事件,通过代理发送请求 client.on('Fetch.requestPaused', async (e) => { const { requestId, request } = e try { const isHttps = request.url.startsWith('https') const fetchResponse = await fetch(request.url, { method: request.method, headers: request.headers, body: request.postData, agent: isHttps ? new HttpsProxyAgent(`http://${proxyHost}:${proxyPort}`) : new HttpProxyAgent(`http://${proxyHost}:${proxyPort}`) }) const body = await fetchResponse.arrayBuffer() // 将代理请求的结果返回给页面 await client.send('Fetch.fulfillRequest', { requestId, responseCode: fetchResponse.status, responseHeaders: Object.fromEntries(fetchResponse.headers.entries()), body: Buffer.from(body).toString('base64') }) } catch (err) { await client.send('Fetch.failRequest', { requestId, errorReason: 'Failed' }) } }) }
内容的提问来源于stack exchange,提问作者Sean Berrie
相关产品推荐
相关产品推荐

