入门

Puppeteer 浏览器自动化与指纹配置文件

将 Puppeteer 与指纹一致的浏览器配置文件集成的完整指南, 包括代理支持和生产部署。

文档中心

想直接看维护中的产品文档?

这篇文章对应的主题已经有文档中心页面。需要规范流程、当前参数和长期参考时,优先看 docs。

简介

Puppeteer 是 Google 的 Node.js 库, 用于通过 Chrome DevTools Protocol (CDP) 控制 Chrome。它提供导航、截图捕获、表单交互、网络拦截等高级 API。BotBrowser 用能产生由配置文件控制的一致指纹输出的二进制文件替换标准 Chromium。Puppeteer 处理自动化, BotBrowser 处理身份。

本指南涵盖完整集成: 安装、启动配置、视口管理、代理设置、CDP 访问、Linux 服务器上的生产部署以及常见故障排除。

隐私影响: 为什么 Puppeteer + BotBrowser

标准 Puppeteer 启动的原版 Chromium 会暴露真实主机的指纹。每个浏览器实例共享相同的 GPU、字体、屏幕分辨率和平台特征。navigator.webdriver 等自动化指标也存在, 表明浏览器正被程序控制。

使用 BotBrowser, 每个 Puppeteer 实例可以加载不同的指纹配置文件, 赋予其独特的浏览器身份。指纹在引擎级别应用, 在任何页面加载和任何 JavaScript 执行之前。你的 Puppeteer 自动化代码完全不需要更改。身份控制在启动配置级别完成。

技术背景

为什么用 puppeteer-core 而非 puppeteer

标准 puppeteer npm 包捆绑了自己的 Chromium 二进制文件。安装时它会下载 Puppeteer 团队管理的特定 Chromium 版本。这个二进制文件不包含 BotBrowser 的指纹控制能力。

puppeteer-core 包提供相同的 API 但不包含捆绑浏览器。它要求你在启动时指定 executablePath, 这正是你将 Puppeteer 指向 BotBrowser 二进制文件的方式。

# 安装 puppeteer-core, 不是 puppeteer
npm install puppeteer-core

defaultViewport 设置

Puppeteer 有一个关键的默认行为: 它在每个新页面上设置 800x600 像素的 defaultViewport。这会覆盖 BotBrowser 指纹配置文件中定义的任何视口尺寸, 导致报告的屏幕大小 (来自配置文件) 和实际视口大小 (Puppeteer 的 800x600) 之间不匹配。

始终设置 defaultViewport: null 以防止此覆盖, 让 BotBrowser 配置文件控制视口尺寸。

CDP 访问

Puppeteer 通过 CDPSession 对象提供直接 CDP 访问。这对 BotBrowser 很重要, 因为一些高级功能通过自定义 CDP 命令控制:

// 浏览器级 CDP 会话
const cdpSession = await browser.target().createCDPSession();

// BotBrowser CDP 命令
await cdpSession.send('BotBrowser.setCustomHeaders', {
  headers: { 'X-Custom': 'value' }
});

注意 BotBrowser CDP 命令必须发送到浏览器级会话, 而非页面级会话。使用 page.createCDPSession() 对 BotBrowser 特有命令会导致 "method not found" 错误。

常见方法及其局限性

使用 Puppeteer 捆绑浏览器

Puppeteer 的捆绑 Chromium 适用于基本自动化但不提供指纹控制。每个实例有相同的指纹, 自动化信号可被检测。

隐身插件

puppeteer-extra-plugin-stealth 包通过 JavaScript 注入修补一些自动化指标。然而, 它在错误的层面运作。JavaScript 注入发生在页面创建之后, 可通过时序分析、原型链检查和其他技术检测。它也不控制 Canvas 输出、WebGL 渲染器字符串或字体可用性等渲染级信号。

手动 User-Agent 设置

Puppeteer 允许用 page.setUserAgent() 设置自定义 User-Agent。这改变了一个信号但所有其他信号 (平台、字体、GPU、屏幕指标) 保持真实值。User-Agent 与其他信号之间的不一致本身就是可检测的信号。

BotBrowser 的方案

BotBrowser 通过 puppeteer.launch() 中的标准 executablePath 参数与 Puppeteer 集成。无需插件、补丁或中间件。

零代码集成

将 BotBrowser 添加到现有 Puppeteer 项目只需更改启动配置。所有页面级代码 (选择器、导航、数据提取) 保持完全相同。

配置与使用

前提条件

  • BotBrowser 二进制文件 (从 GitHub 下载)
  • 指纹配置文件 (.enc 格式)
  • Node.js 18+
  • npm install puppeteer-core

确保 BotBrowser 二进制文件有执行权限:

chmod +x /path/to/botbrowser/chrome

基本启动

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
    ],
    headless: true,
    defaultViewport: null, // 关键: 让配置文件控制视口
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');

  const title = await page.title();
  console.log('Page title:', title);

  await browser.close();
})();

配置文件 + 代理 + 区域设置

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--proxy-server=socks5://user:pass@proxy:1080',
    '--bot-config-timezone=Europe/London',
    '--bot-config-locale=en-GB',
    '--bot-config-languages=en-GB,en',
  ],
  headless: true,
  defaultViewport: null,
});

完整身份设置

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--proxy-server=socks5://user:pass@us-proxy:1080',
    '--bot-config-timezone=America/New_York',
    '--bot-config-locale=en-US',
    '--bot-config-languages=en-US,en',
    '--bot-inject-random-history',
    '--bot-bookmarks=[{"title":"Google","type":"url","url":"https://www.google.com"}]',
    '--bot-cookies=@/path/to/cookies.json',
    '--bot-always-active',
  ],
  headless: true,
  defaultViewport: null,
});

多身份

async function createSession(profilePath, proxyUrl, timezone) {
  const args = [
    `--bot-profile=${profilePath}`,
  ];
  if (proxyUrl) args.push(`--proxy-server=${proxyUrl}`);
  if (timezone) args.push(`--bot-config-timezone=${timezone}`);

  const browser = await puppeteer.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args,
    headless: true,
    defaultViewport: null,
  });

  return browser;
}

// 启动多个不同身份
const sessions = await Promise.all([
  createSession('/profiles/win11-us.enc', 'socks5://u:p@us:1080', 'America/New_York'),
  createSession('/profiles/win11-de.enc', 'socks5://u:p@de:1080', 'Europe/Berlin'),
  createSession('/profiles/android-jp.enc', 'socks5://u:p@jp:1080', 'Asia/Tokyo'),
]);

Ubuntu 上的 Headless 运行

对于 Linux 服务器, 设置 DISPLAY 环境变量:

const puppeteer = require('puppeteer-core');

// 启动前设置 DISPLAY
process.env.DISPLAY = ':10.0';

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
  ],
  headless: true,
  defaultViewport: null,
});

或在 shell 中运行脚本前设置:

DISPLAY=:10.0 node script.js

验证

通过检查指纹信号验证集成:

const page = await browser.newPage();
await page.goto('https://example.com');

const fingerprint = await page.evaluate(() => ({
  userAgent: navigator.userAgent,
  platform: navigator.platform,
  languages: navigator.languages,
  hardwareConcurrency: navigator.hardwareConcurrency,
  deviceMemory: navigator.deviceMemory,
  webdriver: navigator.webdriver,
  screenWidth: screen.width,
  screenHeight: screen.height,
  innerWidth: window.innerWidth,
  innerHeight: window.innerHeight,
  dpr: devicePixelRatio,
  touchPoints: navigator.maxTouchPoints,
}));

console.log('Fingerprint:', JSON.stringify(fingerprint, null, 2));
Puppeteer + BotBrowser 架构 puppeteer-core 自动化 API 无捆绑浏览器 BotBrowser 自定义 Chromium 二进制 基于配置文件的身份 CDP defaultViewport: null + --bot-profile = 一致的身份 相同的 Puppeteer API, 每个实例不同的浏览器身份

最佳实践

  • 始终设置 defaultViewport: null 这是最重要的配置。没有它, Puppeteer 会将配置文件的视口覆盖为 800x600。
  • 使用 puppeteer-core, 不要用完整的 puppeteer 包。完整包会下载不必要的 Chromium 二进制文件。
  • 使用绝对路径 设置 --bot-profile 和其他基于文件的标志。相对路径可能因工作目录不同而解析错误。
  • 完成后关闭浏览器实例。 每个实例是一个 Chrome 进程。不关闭会泄漏内存和 CPU。
  • 在 Linux 服务器上设置 DISPLAY=:10.0, 即使是 headless 模式。
  • 优雅地处理错误。 将启动和导航包装在 try/catch 块中。浏览器启动可能因缺少依赖或路径不正确而失败。

常见问题

能否使用完整的 puppeteer 包而非 puppeteer-core?

技术上可以, 但它会在 npm install 期间下载一个不必要的 Chromium 二进制文件。使用 puppeteer-core 以节省磁盘空间并明确表示你在使用自定义浏览器二进制文件。

还需要 puppeteer-extra 或隐身插件吗?

不需要。BotBrowser 在引擎级别处理指纹控制。隐身插件添加的 JavaScript 级补丁在 BotBrowser 下是不必要的, 并可能干扰其运作。

为什么我的视口显示为 800x600?

你忘记在启动选项中设置 defaultViewport: null。这是 Puppeteer 的默认行为。添加 defaultViewport: null 让 BotBrowser 配置文件控制视口。

如何处理代理认证?

BotBrowser 扩展了 --proxy-server 以接受嵌入的凭据: --proxy-server=socks5://user:pass@host:port。不要使用 Puppeteer 的 page.authenticate() 进行代理认证, 因为它可能禁用 BotBrowser 的自动地理检测。

如何调试配置文件未加载的问题?

检查以下常见问题:

  1. 配置文件路径是绝对路径且文件存在
  2. BotBrowser 二进制文件有执行权限
  3. 使用 --bot-internal --v=1 标志启用调试日志
  4. 检查浏览器的控制台输出是否有配置文件加载错误

需要什么 Node.js 版本?

推荐 Node.js 18 或更高版本。puppeteer-core 最低需要 Node.js 16。

能否使用 TypeScript?

可以。puppeteer-core 包含 TypeScript 定义:

import puppeteer, { Browser, Page } from 'puppeteer-core';

总结

将 BotBrowser 与 Puppeteer 集成需要安装 puppeteer-core, 将 executablePath 指向 BotBrowser 二进制文件, 在启动参数中添加 --bot-profile, 并设置 defaultViewport: null。所有标准 Puppeteer 功能无需修改即可工作。

相关主题请参阅 Playwright 入门 了解 Playwright 对应方案, CLI 食谱 了解标志组合, Headless 服务器设置 了解生产部署, 以及 配置文件管理 了解配置文件组织。

#Puppeteer#Automation#快速开始#Tutorial

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。