Puppeteer中代理如何工作?
Puppeteer通过Chrome启动参数配置代理。--proxy-server设置的地址将应用于该浏览器所有页面。HTTP代理认证信息无法通过启动参数传递,需在页面打开后通过page.authenticate提交,Puppeteer会自动响应代理的认证请求。
示例使用IP 198.51.100.23,HTTP端口8000,SOCKS5端口1080,用户名spx_user,密码spx_pass。
npm install puppeteer如何连接HTTP代理并进行认证?
在launch的args中添加--proxy-server=198.51.100.23:8000,创建newPage后立即通过page.authenticate传入用户名和密码。由于需要为每个页面单独认证,每次创建新页面时都需要重复此调用。
HTTPS网站可正常打开。浏览器会建立CONNECT隧道并在其中进行加密通信。
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
headless: true,
args: ["--proxy-server=http://198.51.100.23:8000"],
});
const page = await browser.newPage();
await page.authenticate({ username: "spx_user", password: "spx_pass" });
await page.goto("https://api.ipify.org", { waitUntil: "domcontentloaded" });
console.log(await page.evaluate(() => document.body.innerText)); // proxy IP
await browser.close();如何使用SOCKS5代理?
在--proxy-server中输入socks5://地址即可。但Chrome不支持SOCKS代理的用户名和密码认证,因此page.authenticate不适用于SOCKS5。要使用SOCKS5连接,请在仪表板中注册运行此代码的服务器的IPv4,使用IP认证。
如果需要使用用户名和密码连接,最简单的方法是使用同一IP的HTTP端口。由于是同一IP,目标网站看到的位置相同。
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
args: ["--proxy-server=socks5://198.51.100.23:1080"], // server IP is authorized in the dashboard
});
const page = await browser.newPage();
await page.goto("https://api.ipify.org");
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();如何用不同IP同时启动多个浏览器?
Chrome每个浏览器实例只能使用一个代理IP。如需不同IP,需分别启动浏览器。以下代码通过API获取ip:port:user:pass列表,用前3个分别启动浏览器并打印各页面显示的IP。
同时开启过多浏览器会占用大量内存。建议设置任务队列并限制并发浏览器实例数。
import puppeteer from "puppeteer";
const KEY = "YOUR_API_KEY";
const res = await fetch("https://socks5proxy.io/api/v1/proxies/download?format=ip:port:user:pass&protocol=http", {
headers: { Authorization: "Bearer " + KEY },
});
const lines = (await res.text()).trim().split("\n").slice(0, 3);
await Promise.all(lines.map(async (line) => {
const [ip, port, user, pass] = line.trim().split(":");
const browser = await puppeteer.launch({ args: ["--proxy-server=http://" + ip + ":" + port] });
try {
const page = await browser.newPage();
await page.authenticate({ username: user, password: pass });
await page.goto("https://api.ipify.org", { timeout: 30000 });
console.log(ip, await page.evaluate(() => document.body.innerText));
} finally {
await browser.close();
}
}));如何更快打开页面?
经代理传输的图片、字体、视频会消耗额外带宽和时间。若仅需文本数据,可通过page.setRequestInterception拦截非必要资源请求,既提升速度又节省共享套餐的月流量配额。
waitUntil参数也很关键。networkidle0会等待所有请求完成可能导致延迟,建议改用page.waitForSelector在目标元素出现后立即进入下一步。
await page.setRequestInterception(true);
page.on("request", (req) => {
const type = req.resourceType();
if (type === "image" || type === "font" || type === "media") req.abort();
else req.continue();
});能否在单个浏览器中使用不同IP打开不同页面?
Chrome的--proxy-server参数会全局生效,难以实现页面级IP切换。Puppeteer 22+支持在browser.createBrowserContext中设置proxyServer选项,实现不同上下文使用不同代理。上下文间cookie和存储隔离,适合多账号操作。
通过page.authenticate传递账号密码即可为上下文创建的页面设置认证,比启动多个浏览器更节省内存。
import puppeteer from "puppeteer";
const browser = await puppeteer.launch();
const context = await browser.createBrowserContext({ proxyServer: "http://198.51.100.23:8000" });
const page = await context.newPage();
await page.authenticate({ username: "spx_user", password: "spx_pass" });
await page.goto("https://api.ipify.org");
console.log(await page.evaluate(() => document.body.innerText));
await context.close();
await browser.close();如何像该国用户一样浏览?
使用page.setExtraHTTPHeaders设置Accept-Language,通过page.emulateTimezone调整时区,确保与IP国家一致。语言或时区不匹配可能导致页面显示异常。
通过page.setViewport设置窗口尺寸,需要手机视图时可使用puppeteer的KnownDevices配置传入page.emulate方法。
await page.setExtraHTTPHeaders({ "Accept-Language": "ja-JP,ja;q=0.9" });
await page.emulateTimezone("Asia/Tokyo");
await page.setViewport({ width: 1366, height: 900 });如何保持长时间运行任务的浏览器稳定性?
对于全天运行的任务,建议在处理一定数量的页面后关闭并重新启动浏览器,而不是一直保持打开状态。长时间运行的浏览器会逐渐占用更多内存,一旦出现错误,后续任务可能会全部停止。
每个页面务必在try和finally中调用page.close,并为goto设置超时以避免无响应页面卡住。失败任务可用新代理启动浏览器重试。
记录各代理的响应时间和错误率,有助于识别慢速节点并向客服反馈,或调整任务分配策略。
常见错误如何解决?
net::ERR_INVALID_AUTH_CREDENTIALS或407错误表示page.authenticate值错误或未在newPage后调用。请确保在每个页面的goto操作前完成调用。
net::ERR_PROXY_CONNECTION_FAILED表示地址或端口错误。请确认HTTP地址使用HTTP端口,SOCKS5地址使用SOCKS5端口。若SOCKS5连接被拒绝,请检查服务器出口IP是否已注册到IP认证列表中。