在这篇 Puppeteer
User Agent 指南中,您将会看到:
- 为什么在 网页抓取 中设置
User-Agent
头至关重要 Puppeteer
中默认的 User Agent 是什么样的- 如何覆盖默认的 Chrome 无头浏览器 User Agent
- 如何在
Puppeteer
中实现 User Agent 轮换 - 如何使用
Puppeteer Extra
来匿名化 User Agent
让我们开始吧!
为什么需要设置自定义 User Agent
User-Agent
头是客户端在通过 HTTP 请求联系服务器时用于标识自身的字符串。它通常包括关于请求来源的机器和/或应用程序的信息。这个头由网页浏览器、HTTP 客户端或任何执行网页请求的软件设置。
下面是 Chrome 在请求网页时设置的 User Agent 字符串示例:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
上述 User Agent 字符串由以下组件组成:
Mozilla/5.0
:最初用于表示与 Mozilla 浏览器的兼容性,现在这个前缀被包含在内以实现更广泛的兼容性。Windows NT 10.0; Win64; x64
:指示操作系统(Windows NT 10.0
)、平台(Win64
)和系统架构(x64
)。AppleWebKit/537.36
:指的是 Chrome 使用的浏览器引擎。(KHTML, like Gecko)
:表示与 KHTML 和 Gecko 排版引擎的兼容性。Chrome/127.0.0.0
:指定浏览器名称和版本。Safari/537.36
:表示与 Safari 的兼容性。
基本上,User Agent 字符串可以揭示请求是来自知名浏览器还是其他类型的软件。
大多数 网页抓取机器人 和自动化脚本最常见的错误是使用默认的或非浏览器的 User Agent。这些值很容易被用于保护网页的反机器人措施检测到。通过分析 User-Agent
头,服务器可以确定请求是否可能来自自动化的机器人。
欲了解更多详细信息,请查看我们的 网页抓取的 User Agent 指南。
默认的 Puppeteer User Agent 是什么?
Puppeteer
通过控制一个特殊版本的真实网页浏览器来自动化浏览器任务。默认情况下,它运行特定版本的 Chrome,尽管它也支持 Firefox。因此,您可能认为 Puppeteer
中的默认 User Agent 将与所控制的 Chrome 版本设置的 User Agent 匹配。然而,事实并非如此……
原因是 Puppeteer
默认以无头模式启动浏览器。当浏览器在无头模式下运行时,它们通常会设置一个独特的 User Agent。截至当前版本,默认的 Puppeteer
User Agent 如下所示:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/127.0.0.0 Safari/537.3
请注意 HeadlessChrome
字符串,它表明 Chrome 正在无头模式下运行。不意外的是,上述字符串正是最新版本的无头 Chrome 的 User Agent。
为了确认上述字符串确实是 Puppeteer
的默认 User Agent,设置一个脚本并导航到 httpbin.io/user-agent 页面。这个 API 端点返回请求的 User-Agent
头,帮助您发现任何浏览器或 HTTP 客户端使用的 User Agent。
创建一个 Puppeteer
脚本,访问目标页面,从主体中获取 API 响应,并打印出来:
import puppeteer from "puppeteer";
(async () => {
// launch the browser and open a new page
const browser = await puppeteer.launch();
const page = await browser.newPage();
// connect to the target page
await page.goto("https://httpbin.io/user-agent");
// extract the body text with the API response
// and print it
const bodyText = await page.evaluate(() => {
return document.body.innerText;
});
console.log(bodyText);
// close the browser and release its resources
await browser.close();
})();
要了解更多关于 Puppeteer
API 的信息,请阅读我们的 使用 Puppeteer
进行网页抓取的指南。
运行上述 Node.js 代码,您将收到以下字符串:
{
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/127.0.0.0 Safari/537.36"
}
请注意,Puppeteer
设置的 User Agent 与之前呈现的字符串相匹配。
问题在于 HeadlessChrome
标识符,它可能会引起 反机器人系统
的警觉。这些系统通过分析传入请求的模式(例如不寻常的 User Agent 字符串)来检测可能指示机器人活动的请求。可疑的请求会被标记并相应地阻止。这就是为什么修改默认的 Puppeteer
User Agent 字符串如此重要!
如何更改 Puppeteer User Agent
更改 User Agent 是如此常见且有用的操作,以至于 Puppeteer
专门提供了一个方法。特别是,Page
类公开了 setUserAgent()
方法。这允许您在该浏览器选项卡中导航到网页时修改 Puppeteer
设置的 User-Agent
。
使用 setUserAgent()
来更改 Puppeteer
的 User Agent,如下所示:
await page.setUserAgent("<your_user_agent>");
现在,通过在 page
上调用 goto()
方法进行的所有 HTTP GET 请求都将具有自定义的 User-Agent
头。请记住,此更改仅适用于特定的 page
对象。如果您打开一个新页面并与之交互,Puppeteer
将使用之前看到的默认 User Agent。
完整的示例如下所示:
import puppeteer from "puppeteer";
(async () => {
// launch the browser and open a new page
const browser = await puppeteer.launch();
const page = await browser.newPage();
// set a custom user agent
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36");
// connect to the target page
await page.goto("https://httpbin.io/user-agent");
// extract the body text with the API response
// and print it
const bodyText = await page.evaluate(() => {
return document.body.innerText;
});
console.log(bodyText);
// close the browser and release its resources
await browser.close();
})();
执行上述脚本,这次结果将是:
{
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
太棒了!从页面提取的 User Agent 字符串与代码中配置的 User Agent 相匹配。您现在知道如何执行 Puppeteer
更改 User Agent 的操作。
在 Puppeteer 中实现 User Agent 轮换
将无头浏览器的 User-Agent
头替换为非无头浏览器的 User Agent 可能不足以避免 反机器人系统。问题在于您的浏览器自动化脚本将表现出非人类行为的模式。如果您使用相同的头和相同的 IP
地址发送大量请求,情况尤其如此。
为了最大限度地降低在 Puppeteer
中被机器人检测到的风险,您需要使请求尽可能多样化。一个有效的方法是为每个请求设置不同的 User Agent。这种策略称为 User Agent 轮换,有助于降低被标记为机器人的可能性。
在接下来的教程部分,您将学习如何在 Puppeteer
中实现 User Agent 轮换!
步骤一:生成随机的 User Agent
获取随机 User Agent 有两种主要方法。第一种是获取有效 User Agent 的列表,并从列表中随机选择一个,正如我们在 Node.js User Agent 指南中所示。
第二种方法是使用第三方 User Agent 生成器库。JavaScript 中最流行的是 user-agents,这是一个可以为您生成有效 User Agent 的包。在本指南中,我们将遵循这种方法!
运行此 npm 命令将 user-agents
库添加到项目的依赖项中:
npm install user-agents
请注意,user-agents
每日更新,确保它始终包含最新的 User Agent。
安装库后,将 UserAgent
对象导入您的 Puppeteer
脚本:
import UserAgent from "user-agents";
现在,您可以使用以下代码生成一个随机的 User Agent 字符串:
const userAgent = new UserAgent().random().toString();
查看官方文档,了解更高级的用法,例如获取特定设备、操作系统的 User Agent 等。
步骤二:设置随机 User Agent
通过调用 Puppeteer
的 setUserAgent()
方法,将随机的 User Agent 字符串传递给 Puppeteer
:
const userAgent = new UserAgent().random().toString();
await page.setUserAgent(userAgent);
现在,通过 page
对象执行的所有请求都将具有随机生成的自定义 User Agent。
步骤三:访问目标页面
在 page
上调用 goto()
方法,在受控的无头浏览器中访问目标网页:
await page.goto("https://httpbin.io/user-agent");
步骤四:整合所有步骤
以下是您的最终 Puppeteer
User Agent 轮换脚本:
import puppeteer from "puppeteer";
import UserAgent from "user-agents";
(async () => {
// launch the browser and open a new page
const browser = await puppeteer.launch();
const page = await browser.newPage();
// generate a random user agent
const userAgent = new UserAgent().random().toString();
// set a random user agent
await page.setUserAgent(userAgent);
// connect to the target page
await page.goto("https://httpbin.io/user-agent");
// extract the body text with the API response
// and print it
const bodyText = await page.evaluate(() => {
return document.body.innerText;
});
console.log(bodyText);
// close the browser and release its resources
await browser.close();
})();
运行脚本几次,您应该会看到不同的 User Agent。
就是这样!在 Puppeteer
中的 User Agent 轮换逻辑运作良好。
使用 puppeteer-extra-plugin-anonymize-ua
在 Puppeteer 中设置自定义 User Agent
上述更改 Puppeteer
User Agent 的方法是有效的,但它们有一个显著的缺点。userAgent()
方法只更改特定页面会话的 User Agent,而不是跨所有浏览器选项卡。
为了确保 Puppeteer
永远不使用默认的 User Agent,您可以使用 puppeteer-extra-plugin-anonymize-ua
插件,该插件来自 Puppeteer Extra
。如果您不熟悉该项目,Puppeteer Extra
通过添加对社区定义的插件的支持来扩展 Puppeteer
。您可以在我们的 Puppeteer Extra Stealth 插件
指南中了解更多。
puppeteer-extra-plugin-anonymize-ua
插件可以匿名化 Puppeteer
设置的 User Agent。要安装 puppeteer-extra
和必要的插件,请运行以下命令:
npm install puppeteer-extra puppeteer-extra-plugin-anonymize-ua
接下来,从 puppeteer-extra
导入 puppeteer
,并从 puppeteer-extra-plugin-anonymize-ua
导入 AnonymizeUAPlugin
:
import puppeteer from "puppeteer-extra";
import AnonymizeUAPlugin from "puppeteer-extra-plugin-anonymize-ua";
配置 puppeteer-extra-plugin-anonymize-ua
以生成随机的 User Agent,并使用 Puppeteer Extra
的 use()
方法将其注册为插件:
puppeteer.use(
AnonymizeUAPlugin({
customFn: () => new UserAgent().random().toString(),
})
);
现在,尝试使用两个不同的 page
对象在两个不同的选项卡中访问页面:
import puppeteer from "puppeteer-extra";
import AnonymizeUAPlugin from "puppeteer-extra-plugin-anonymize-ua";
import UserAgent from "user-agents";
(async () => {
// configure and register the
// puppeteer-extra-plugin-anonymize-ua plugin
puppeteer.use(
AnonymizeUAPlugin({
customFn: () => new UserAgent().random().toString(),
})
);
// launch the browser and open a new page
const browser = await puppeteer.launch();
// open a new page
const page1 = await browser.newPage();
// connect to the target page
await page1.goto("https://httpbin.io/user-agent");
// extract the body text with the API response
// and print it
const bodyText1 = await page1.evaluate(() => {
return document.body.innerText;
});
console.log(bodyText1);
// open a new page
const page2 = await browser.newPage();
// connect to the target page
await page2.goto("https://httpbin.io/user-agent");
// extract the body text with the API response
// and print it
const bodyText2 = await page2.evaluate(() => {
return document.body.innerText;
});
console.log(bodyText2);
// close the browser and release its resources
await browser.close();
})();
结果将是两个不同的 User Agent,如下所示:
{
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1"
}
{
"user-agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36"
}
这两个 User Agent 是不同的,且都不是默认的 Puppeteer
User Agent。这是因为 puppeteer-extra-plugin-anonymize-ua
使用在 customFn
函数中指定的随机 User Agent 来定制每个 page
对象。这样,Puppeteer
将永远不会暴露其默认的 User Agent!
结论
在本文中,您探讨了设置 User-Agent
头的重要性,并看到了默认的 Puppeteer
User Agent 是什么样子的。您学习了如何覆盖该值并实现 User Agent 轮换以避免基本的反抓取系统。然而,更复杂的系统仍然可以检测并阻止您的自动化请求。为了防止 IP
被封禁,您可以在 Puppeteer
中配置代理,但即使这样也可能不够!
为了获得更有效的解决方案,试试 Scraping Browser —— 一个与 Puppeteer
和任何其他浏览器自动化工具集成的下一代浏览器。Scraping Browser
可以轻松地为您绕过反机器人技术,同时避免浏览器指纹识别。在幕后,它依赖于 User Agent 轮换、IP 轮换 和 CAPTCHA
解决 等功能。浏览器自动化从未如此简单!
立即注册并开始您的免费试用。