QueryList无头搜索
背景介绍
在数据采集和网络爬虫领域,模拟真实用户行为、获取动态渲染的页面内容一直是关键需求。传统的基于curl或file_get_contents的采集方式,往往无法执行JavaScript,从而难以抓取像百度搜索结果这样依赖前端渲染的数据。
“无头浏览器”(Headless Browser)技术的出现解决了这一问题。它让浏览器在无图形界面的后台运行,但能完整地解析页面、执行脚本。结合PHP的QueryList库和其Puppeteer插件,开发者可以用熟悉的PHP语法,通过控制无头Chrome浏览器来实现复杂的网页交互与数据抓取。
本文介绍的方法,正是利用QueryList、puphpeteer(PHP版的Puppeteer桥接工具)和Chrome,实现了一个可控的、可调试的百度搜索爬虫示例。
核心条件与准备
在开始之前,需要确保环境满足以下条件:
安装Node.js:
puphpeteer依赖于Node.js环境来驱动Puppeteer。安装PHP包:
nesk/puphpeteer:通过npm install @nesk/puphpeteer安装。jaeger/querylist和jaeger/querylist-puppeteer:推荐使用Composer安装。
PHP配置:确保
proc_open函数未被禁用,因为PHP需要用它来启动子进程(Chrome浏览器)。环境建议:原作者提到“不建议用 linux”,这可能是指在某些Linux环境下配置和运行Puppeteer(如依赖库缺失)相对复杂,但在有经验后仍可正常运行。
核心代码与解析
以下代码展示了完整的流程:启动浏览器 -> 访问百度 -> 输入关键词并搜索 -> 等待结果加载 -> 获取页面HTML -> 使用QueryList规则抽取数据 -> 执行额外操作(如保存图片和截图)-> 关闭浏览器。
<?php require ('./vendor/autoload.php'); use QL\QueryList; use QL\Ext\Chrome; $ql = QueryList::getInstance(); // 注册Chrome插件,默认方法名为 chrome $ql->use(Chrome::class); $html = $ql->chrome(function ($page, $browser) { // 1. 访问百度首页 $page->goto('https://www.baidu.com/'); sleep(3); // 等待页面加载,方便观察 // 2. 输入关键词并搜索 $wd = 'lovesanqing'; $page->type("input[id='kw']", $wd); sleep(1); $page->click("input[type='submit']"); sleep(3); // 等待搜索结果加载 // 3. 获取渲染完成后的页面HTML $html = $page->content(); // 4. 使用QueryList规则抽取所需数据 $rules = [ 'title' => ['#content_left h3 a', 'text'], // 标题 'url' => ['#content_left h3 a', 'href'], // 链接 'description' => ['div.c-abstract', 'text'], // 描述 'img' => ['#content_left .general_image_pic a img', 'src'], // 图片 ]; $ql = QueryList::html($html); $rt = $ql->rules($rules)->query()->getData(); print_r($rt->all()); // 5. 数据处理:保存图片到本地 foreach ($rt->all() as $item) { if (isset($item['img'])) { $imgUrl = $item['img']; $imageContent = file_get_contents($imgUrl); $filename = './images/' . time() . rand(1, 999999) . '.jpg'; file_put_contents($filename, $imageContent); } } // 6. 额外操作:页面截图(裁剪特定区域) $screenshotPath = './images/' . time() . rand(1, 999999) . '.jpg'; $page->screenshot([ 'path' => $screenshotPath, 'clip' => ['x' => 900, 'y' => 4470, 'width' => 125, 'height' => 40] ]); sleep(10); $browser->close(); // 闭包必须返回页面的HTML内容 return $html; }, [ 'headless' => true, // 设为false可显示浏览器窗口,方便调试 'devtools' => false, // 是否打开开发者工具 ])->find('title')->text(); // 获取页面标题 // 输出页面标题 echo $html;
代码关键点说明:
sleep()的使用:代码中多次使用sleep(),目的是等待页面元素加载和交互完成。在实际项目中,更推荐使用$page->waitForSelector()等智能等待方法,以提高效率和稳定性。headless选项:设置为false时会弹出Chrome窗口,非常适合开发调试;生产环境应设为true。数据处理:在获取到数据集合后,代码示例展示了如何遍历并保存图片,以及如何进行页面截图。
总结
本文提供了一种利用PHP结合QueryList和Puppeteer(通过puphpeteer)实现无头浏览器采集百度搜索结果的可行方案。
优点:
真实模拟:能完整执行JavaScript,抓取任何动态网页内容。
开发友好:使用PHP语法,并支持可视化调试(
headless: false)。功能丰富:除了数据抽取,还能实现截图、PDF生成、自动化测试等扩展功能。
注意事项与改进建议:
性能开销:启动浏览器进程消耗资源较大,不适合大规模的并发采集。可以考虑复用浏览器实例或使用代理池。
稳定性:依赖外部进程(Node.js和Chrome),需做好异常捕获和超时重试机制。
反爬策略:百度等网站有反爬机制,频繁请求可能触发验证码或IP封禁。建议合理设置请求间隔、使用代理IP,并妥善处理可能出现的验证码(代码中注释了
$page->focus()相关操作)。依赖管理:在Linux服务器上部署时,需确保安装所有Chromium依赖库,这是“不建议用 linux”的潜在原因,但通过正确配置可以解决。
总的来说,对于需要与复杂网页交互的采集任务,这是一个强大且灵活的技术组合。开发者可以根据自身需求和环境,在示例代码基础上进行优化和扩展。
请先 登录后发表评论 ~