必须显式将 stream_context_create 创建的上下文作为第三个参数传给 file_get_contents,否则 User-Agent 等设置无效;正确结构为 [‘http’=>[‘user_agent’=>’…’,’timeout’=>10,’follow_location’=>true]],且需补充 Accept、Accept-Language 等请求头防拦截。

为什么 stream_context_create 设了 User-Agent 还没效果?
常见错误是只传了 User-Agent,却没把上下文真正用到请求里。PHP 的 file_get_contents 或 fopen 必须显式传入第二个参数(即上下文),否则默认用系统级配置,User-Agent 完全不生效。
- 必须把
stream_context_create返回的资源传给file_get_contents($url, false, $context),第三个参数不能省略或写成null -
file_get_contents默认不走自定义上下文;漏掉这个参数 = 白配 - 某些代理或 CDN 会校验
User-Agent是否“像浏览器”,光设字符串不够,得带常见值(如Mozilla/5.0开头)
stream_context_create 的正确参数结构长什么样?
它接受一个二维数组,第一层是协议名(如 http),第二层才是具体选项。错写成一维数组、或把 http 拼错成 https(即使 URL 是 https)都会静默失败。
- 必须用
['http' => [……]],不是['https' => [……]]—— PHP 底层统一走http协议处理器 -
user_agent键名是小写,不是User-Agent或USER_AGENT - 如果要支持重定向,得加
'follow_location' => true,否则 302 会直接返回空内容 - 超时建议设
'timeout' => 10,避免卡死(默认是无限等待)
$context = stream_context_create(['http' => [ 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'timeout' => 10, 'follow_location' => true ] ]); $content = file_get_contents('https://example.com', false, $context);
遇到 403 或空响应,除了 User-Agent 还要补什么?
很多网站不仅看 User-Agent,还检查 Accept、Accept-Language,甚至要求 Connection: close。单纯塞个 UA 很容易被当成爬虫拦截。
- 加上
'header' => "Accept: text/html,application/xhtml+xmlrnAccept-Language: zh-CN,zh;q=0.9"(注意换行用rn) - 有些站点拒绝 HTTP/1.0,默认用 HTTP/1.0 发起请求,可加
'method' => 'GET'显式声明 - 若目标站强制 HTTPS 且证书异常,需加
'ssl' => ['verify_peer' => false, 'verify_peer_name' => false](仅调试用,生产环境禁用) - 别用太短或太怪的 UA 字符串,比如
test/1.0大概率 403
和 cURL 比,stream_context_create 有什么硬伤?
它轻量、不用装扩展,但功能边界明显:不支持 Cookie 自动管理、无法获取响应头、没法复用连接、重定向深度不可控。一旦需求变复杂,立刻卡住。
立即学习 “PHP 免费学习笔记(深入)”;
- 想读响应状态码?
file_get_contents不暴露,只能靠$http_response_header全局变量(不稳定) - 需要登录态维持?
stream_context_create不存 Cookie,每次都是无状态请求 - 并发多个请求时,没有连接池,性能比 cURL 差不少
- 错误提示极弱:
file_get_contents失败只返回false,得开error_get_last()才能看到底层报错
真要模拟浏览器行为,尤其是涉及登录、跳转、JS 渲染前的 HTML 抓取,cURL 或 Puppeteer 才是正解。用 stream_context_create 就图个简单,别指望它扛复杂场景。