Chrome PHP 库完全指南:从入门到高级用法

什么是 Chrome PHP?

Chrome PHP 是一个功能强大的 PHP 库,允许开发者通过编程方式控制 Chrome 或 Chromium 浏览器。它基于 Chrome DevTools 协议,提供了简洁易用的 API,让你能够模拟人类在浏览器中的几乎所有操作 —— 从简单的页面导航到复杂的表单提交、JavaScript 执行和数据提取。

该项目采用 MIT 许可证 开源,允许在商业和非商业项目中自由使用和修改。

安装与环境要求

系统要求

  • PHP 7.4 或更高版本
  • 已安装 Chrome 或 Chromium 浏览器(推荐版本 80+)
  • 支持的操作系统:Windows、macOS、Linux

安装方法

通过 Composer 安装:

1
composer require chrome-php/chrome

基础用法

基本流程示例

以下是使用 Chrome PHP 的典型流程,包含浏览器启动、页面操作和资源清理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
use HeadlessChromium\BrowserFactory;

// 初始化浏览器工厂
$browserFactory = new BrowserFactory();

// 启动无头 Chrome 浏览器
$browser = $browserFactory->createBrowser();

try {
// 创建新页面并导航到指定 URL
$page = $browser->createPage();
$page->navigate('http://example.com')->waitForNavigation();

// 获取页面标题
$pageTitle = $page->evaluate('document.title')->getReturnValue();
echo "页面标题: {$pageTitle}\n";

// 截图
$page->screenshot()->saveToFile('/path/to/screenshot.png');

// 生成 PDF
$page->pdf(['printBackground' => false])->saveToFile('/path/to/page.pdf');
} finally {
// 确保浏览器关闭
$browser->close();
}

核心功能详解

浏览器配置

创建浏览器时可以指定多种配置参数:

1
2
3
4
5
6
7
8
9
10
11
$browser = $browserFactory->createBrowser([
'windowSize' => [1280, 720], // 窗口尺寸
'userAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...', // 自定义 User-Agent
'headless' => true, // 是否启用无头模式(默认 true
'args' => [
'--no-sandbox',
'--disable-gpu',
'--remote-debugging-port=9222'
], // Chrome 启动参数
'timeout' => 60000 // 启动超时时间(毫秒)
]);

页面操作

导航与等待

1
2
3
4
5
// 基本导航
$page->navigate('https://example.com')->waitForNavigation();

// 等待导航完成(带超时设置)
$page->navigate('https://example.com')->waitForNavigation(5000); // 5秒超时

获取页面内容

1
2
3
4
5
6
// 获取完整 HTML
$html = $page->getHtml();

// 执行 JavaScript 并获取结果
$title = $page->evaluate('document.title')->getReturnValue();
$linksCount = $page->evaluate('document.querySelectorAll("a").length')->getReturnValue();

视口设置

1
2
3
4
5
// 设置视口大小
$page->setViewport(1920, 1080)->await();

// 获取当前视口信息
$viewport = $page->evaluate('[window.innerWidth, window.innerHeight]')->getReturnValue();

User-Agent 设置

1
2
3
4
5
// 设置自定义 User-Agent
$page->setUserAgent('My Custom User Agent')->await();

// 验证设置结果
$userAgent = $page->evaluate('navigator.userAgent')->getReturnValue();

DOM 操作与数据提取

元素查找

Chrome PHP 提供了强大的 DOM 搜索能力,支持 XPath 和 CSS 选择器:

1
2
3
4
5
6
7
8
// 获取 DOM 文档对象
$document = $page->dom();

// 使用 XPath 查找元素
$elements = $document->search("//div[@class='article']");

// 使用 CSS 选择器查找元素
$elements = $document->search(".article");

元素属性与内容提取

1
2
3
4
5
6
7
8
9
10
11
// 提取元素文本
$title = $element->getText();

// 获取元素属性
$href = $element->getAttribute('href');
$src = $element->getAttribute('src');

// 检查属性是否存在
if ($element->hasAttribute('data-id')) {
$id = $element->getAttribute('data-id');
}

复杂数据提取示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$articles = [];
$elements = $document->search("//div[@class='post-item']");

foreach ($elements as $element) {
// 提取标题和链接
$titleElement = $document->search(".//h2/a", $element)[0] ?? null;
$title = $titleElement ? $titleElement->getText() : '';
$url = $titleElement ? $titleElement->getAttribute('href') : '';

// 提取图片
$imgElement = $document->search(".//img", $element)[0] ?? null;
$image = $imgElement ? $imgElement->getAttribute('src') : '';

$articles[] = [
'title' => $title,
'url' => $url,
'image' => $image
];
}

键盘操作

模拟键盘输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 输入文本
$page->keyboard()->type('Hello World!');

// 按下并释放单个键
$page->keyboard()->press('Enter');

// 组合键操作(例如 Ctrl+C)
$page->keyboard()
->down('Control')
->press('KeyC')
->up('Control');

// 模拟 Tab 键切换焦点
$page->keyboard()->typeRawKey('Tab');

// 释放所有按键
$page->keyboard()->release();

鼠标操作

模拟鼠标行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 移动到元素并点击
$page->mouse()
->findElement(new CssSelector('#submit-button'))
->click();

// 右键点击
$page->mouse()
->findElement(new XPathSelector('//*[@id="menu"]'))
->rightClick();

// 双击操作
$page->mouse()
->findElement(new CssSelector('.editable'))
->doubleClick();

// 拖拽操作
$page->mouse()
->findElement(new CssSelector('.draggable'))
->dragAndDropTo(new CssSelector('.drop-zone'));

截图功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 截取整个页面
$page->screenshot()->saveToFile('full-page.png');

// 截取可见区域
$page->screenshot([
'captureBeyondViewport' => false
])->saveToFile('visible-area.png');

// 截取特定元素
$document->search("//div[@id='content']")[0]
->screenshot()
->saveToFile('content-element.png');

// 获取截图的 Base64 编码
$base64 = $page->screenshot()->getBase64();

PDF 生成

生成高质量 PDF 文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 基本 PDF 生成
$page->pdf()->saveToFile('document.pdf');

// 自定义 PDF 选项
$pdfOptions = [
'landscape' => false, // 是否横向
'printBackground' => true, // 是否打印背景
'displayHeaderFooter' => true, // 是否显示页眉页脚
'headerTemplate' => '<div style="font-size: 8px;">Header: <span class="title"></span></div>',
'footerTemplate' => '<div style="font-size: 8px;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>',
'paperWidth' => 8.5, // 纸张宽度(英寸)
'paperHeight' => 11, // 纸张高度(英寸)
'marginTop' => 0.5, // 上 margin
'marginBottom' => 0.5, // 下 margin
'marginLeft' => 0.5, // 左 margin
'marginRight' => 0.5, // 右 margin
'scale' => 1.0 // 缩放比例
];

$page->pdf($pdfOptions)->saveToFile('custom-document.pdf');

// 直接输出 PDF 到浏览器
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="document.pdf"');
echo base64_decode($page->pdf()->getBase64());

页眉页脚模板支持的特殊类:

  • date - 格式化的打印日期
  • title - 文档标题
  • url - 文档 URL
  • pageNumber - 当前页码
  • totalPages - 总页数

高级功能

执行 JavaScript 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 调用函数并获取结果
$result = $page->callFunction(
'function(a, b) { return a + b; }',
[2, 3] // 函数参数
)->getReturnValue(); // 返回 5

// 处理异步函数(Promise)
$result = $page->callFunction(
'function() {
return new Promise(resolve => {
setTimeout(() => resolve("Done"), 1000);
});
}'
)->getReturnValue(); // 等待 1 秒后返回 "Done"

页面事件监听

1
2
3
4
5
6
7
8
9
// 监听页面加载完成事件
$page->on('load', function () {
echo "Page loaded!\n";
});

// 监听控制台消息
$page->on('console', function ($message) {
echo "Console: {$message}\n";
});

等待元素出现

1
2
3
4
5
// 等待元素出现(超时 5 秒)
$page->waitForSelector('#submit-button', 5000);

// 等待元素消失
$page->waitForSelector('.loading-spinner', 5000, true);

多页面操作

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建多个页面
$page1 = $browser->createPage();
$page2 = $browser->createPage();

// 页面 1 导航到 Google
$page1->navigate('https://google.com')->waitForNavigation();

// 页面 2 导航到 GitHub
$page2->navigate('https://github.com')->waitForNavigation();

// 分别操作不同页面
$title1 = $page1->evaluate('document.title')->getReturnValue();
$title2 = $page2->evaluate('document.title')->getReturnValue();

异常处理

Chrome PHP 定义了多种异常类型,方便精确处理不同错误场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use HeadlessChromium\Exception\OperationTimedOut;
use HeadlessChromium\Exception\ElementNotFoundException;
use HeadlessChromium\Exception\TargetDestroyed;

try {
// 可能抛出异常的操作
$page->navigate('https://example.com')->waitForNavigation(3000);
$element = $document->search("//div[@id='critical']")[0];
} catch (OperationTimedOut $e) {
// 处理超时错误
echo "操作超时: " . $e->getMessage();
} catch (ElementNotFoundException $e) {
// 处理元素未找到错误
echo "元素未找到: " . $e->getMessage();
} catch (TargetDestroyed $e) {
// 处理页面已销毁错误
echo "页面已关闭: " . $e->getMessage();
}

测试与调试

启用调试模式

1
2
3
4
5
$browser = $browserFactory->createBrowser([
'debugLogger' => function ($message) {
file_put_contents('chrome-debug.log', $message . "\n", FILE_APPEND);
}
]);

禁用无头模式

开发调试时,可以禁用无头模式以可视化浏览器操作:

1
2
3
4
$browser = $browserFactory->createBrowser([
'headless' => false,
'devtools' => true // 自动打开开发者工具
]);

最佳实践

  1. 资源管理:始终在 finally 块中关闭浏览器,确保资源释放
  2. 错误处理:使用适当的异常捕获机制处理可能的错误
  3. 性能优化:
    • 避免创建不必要的页面实例
    • 合理设置超时时间
    • 复杂操作考虑使用批处理
  4. 合规性:
    • 尊重网站的 robots.txt 规则
    • 遵守目标网站的使用条款
    • 控制请求频率,避免给服务器带来过大压力

总结

Chrome PHP 为 PHP 开发者提供了一个强大而灵活的工具,用于浏览器自动化和网页数据处理。无论是简单的页面截图、PDF 生成,还是复杂的表单提交和动态内容爬取,Chrome PHP 都能胜任。通过本文介绍的功能和示例,你可以快速上手并发挥其全部潜力,为你的项目增添浏览器自动化能力。

更多详细信息和高级用法,请参考官方 GitHub 仓库:chrome-php/chrome