怎么抓取多个网页_PHP实现多页面批量抓取教程【详解】

2次阅读

php批量抓取网页必须用curl多句柄并发,因file_get_contents()仅支持串行;curl_multi_init()是唯一原生并发方案,需手动管理句柄、轮询状态、读取结果并关闭句柄,否则内存泄漏或无法获取响应。

怎么抓取多个网页_PHP实现多页面批量抓取教程【详解】

PHP 本身没有内置的“批量抓取网页”功能,file_get_contents()cURL 都是单请求模型;真要并发抓多个页面,必须自己组织并发逻辑,否则就是串行——慢、易超时、服务器可能封 IP。

cURL 多句柄实现真正并发请求

PHP 的 curl_multi_init() 是唯一原生支持多 URL 并发发起 http 请求的机制,它不依赖扩展,但需要手动管理句柄、轮询状态、处理错误。

  • 每个 URL 对应一个 cURL 句柄,统一塞进 curl_multi_init() 管理器
  • curl_multi_exec() 启动并持续轮询,直到全部完成(不能只调一次)
  • 必须配合 curl_multi_info_read() 拿到已完成请求的结果,否则拿不到响应体
  • 记得对每个句柄调 curl_close(),否则内存泄漏

示例关键片段:

foreach ($urls as $url) {     $ch = curl_init($url);     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);     curl_setopt($ch, CURLOPT_TIMEOUT, 10);     curl_multi_add_handle($mh, $ch); } while (($exec = curl_multi_exec($mh, $running)) === CURLM_CALL_MULTI_PERFORM); while ($running && $exec === CURLM_OK) {     if (curl_multi_select($mh) !== -1) {         do {             $info = curl_multi_info_read($mh);             if ($info && $info['result'] === CURLE_OK) {                 $content = curl_multi_getcontent($info['handle']);                 // 处理 $content             }             curl_multi_remove_handle($mh, $info['handle']);             curl_close($info['handle']);         } while ($info);     } }

file_get_contents() + stream_context_create() 不适合批量

虽然能用 stream_context_create() 设置超时、UA,但它是同步阻塞的:请求 A 没返回,B 就卡住。哪怕用 set_time_limit(0),也解决不了本质问题。

立即学习PHP免费学习笔记(深入)”;

  • 5 个页面平均 2 秒响应 → 串行就要 10 秒;并发可压到 2–3 秒内
  • 超时设置对单个请求有效,但无法避免整体耗时线性增长
  • 没错误隔离:一个 502 就可能导致后续请求全被跳过(除非你手动 try/catch 每次)

别忽略 DNS、连接、ssl 开销和反爬策略

真实环境中,慢往往不出现在内容下载阶段,而出现在握手环节。尤其批量请求同一域名时,DNS 查询和 TCP/TLS 握手会成为瓶颈。

  • CURLOPT_TCP_NODELAY 和复用连接(CURLOPT_FORBID_REUSE 设为 false)能明显提升吞吐
  • CURLOPT_RESOLVE 手动注入 DNS 缓存,绕过系统 DNS 查询(适合固定目标域名)
  • 多数网站会限制 User-Agent、Referer、请求频率;不带头或间隔太短,直接返回 403 或空页
  • 如果目标页含 JavaScript 渲染内容,cURL 拿不到,得换 Puppeteer/Playwright,PHP 仅作调度

真正难的不是发请求,而是控制节奏、解析响应、重试失败、降频避封——这些逻辑一旦漏掉,脚本上线后就只是个定时报错器。

text=ZqhQzanResources