file_get_contents()不适合作为php爬虫主力,因其无法处理302跳转、缺少user-agent易被403拒绝、不支持gzip解压、超时不可控且中文乱码频发;应首选curl_init()+domdocument组合,通过curlopt_useragent、curlopt_followlocation等选项可控抓取,并配合libxml_use_internal_errors()和mb_convert_encoding()保障解析稳定性。

file_get_contents() 不能当爬虫主力用,它连基础反爬都过不了;真要写 PHP 爬虫,得从 curl_init() + DOMDocument 这套组合起步——不是因为它多高级,而是它可控、可调、不依赖第三方,适合边跑边改。
为什么别一上来就用 file_get_contents()
它看着简单,但实际踩坑率极高:
• 目标页返回 302 跳转时,file_get_contents() 默认不跟,直接返回空或 warning,你连错在哪都不知道
• 没法设 User-Agent,多数站点直接 403 拒绝,还查不出原因
• gzip 压缩页面默认不解压,得手动开 zlib 扩展 + 配 stream_context_create() 的 http[encoding]
• 超时只能靠 default_socket_timeout 全局配置,没法 per-request 控制
• 中文乱码常见,因为没做 mb_convert_encoding() 预处理,getElementsByTagName() 就匹配不到节点
curl_init() 必须配的几个选项
不设这几点,curl_exec() 很可能拿不到有效 HTML:
• CURLOPT_RETURNTRANSFER 必须为 true,否则内容直接 echo 出来,没法解析
• CURLOPT_USERAGENT 要设成真实浏览器 UA,比如 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
• CURLOPT_FOLLOWLOCATION 开启后,必须同步设 CURLOPT_MAXREDIRS(建议 5),否则重定向环会卡死
• CURLOPT_TIMEOUT 建议 10–15 秒,太短容易中断,太长拖慢整体采集节奏
• HTTPS 报证书错误时,优先检查系统 CA 路径,而不是设 CURLOPT_SSL_VERIFYPEER => false —— 后者等于裸奔
DOMDocument 解析 HTML 容易崩在哪
它不是浏览器,对“脏 HTML”容忍度极低:
• 遇到 <img>、
<br>这类自闭合标签没斜杠,或
<p></p> 没闭合,就会报 warning 并结构错乱• 必须提前调用
libxml_use_internal_errors(true),否则解析失败还被 warning 淹没• 加载前务必用
mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8') 或类似方式统一编码,否则中文节点根本找不到• 别信
$dom->saveHTML() 输出“干净 HTML”,它会重排标签顺序、删空格、改属性顺序,导致 XPath 失效
什么时候该换 Goutte 或 Guzzle
当你开始遇到这些情况,说明原生方案已到临界点:
• 需要自动维护 Cookie 登录态,比如抓会员页或翻页带 session 的列表
• 页面里有 JavaScript 渲染的关键数据(DOMDocument 读不到)
• 要批量请求上百 URL 并做并发控制,手写 curl_multi 易出错
• CSS 选择器写起来比 XPath 直观得多,比如 .post-title a 比 //div[contains(@class,"post-title")]/a 更快定位
• 但注意:Goutte 依赖 Symfony 组件,Guzzle 是 HTTP 层,两者都不自带解析逻辑,仍需接 DomCrawler 或自己桥接
curl 就没跟上;是 UTF-8 BOM 残留让 DOMDocument 解析失败却没报错。这些细节不跑一遍真实页面,光看教程永远意识不到。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











