file_get_contents 抓不到新浪新闻首页,因其默认无 user-agent、不支持自动跳转和 cookie 管理,被新浪服务器识别为爬虫而返回 403 或空内容;必须改用 curl 并设置 curlopt_useragent 和 curlopt_encoding 才能正常获取 html。

file_get_contents 和 curl 都能抓,但直接用 file_get_contents 在新浪新闻首页上大概率失败——它会返回空内容或 403,因为新浪对无 User-Agent 的请求做了拦截。
为什么 file_get_contents 经常抓不到新浪新闻列表?
新浪新闻首页(http://news.sina.com.cn/)默认拒绝没有浏览器标识的请求。PHP 默认的 file_get_contents 不带 User-Agent,也不支持自动跳转和 Cookie 管理,容易被当成爬虫封掉。
- 现象:返回空字符串、乱码,或 HTTP 403 / 503 错误
- 根本原因:服务端通过
User-Agent和Accept-Encoding判断是否为真实浏览器 - 解决思路:改用
curl,手动设置请求头 + 编码处理
curl 抓取新浪首页标题的最小可行代码
以下是最简但能跑通的版本,已适配当前(2026年)新浪首页结构(仍使用 h1 + data-client="headline" 类选择器):
<pre class="brush:php;toolbar:false;">$url = 'http://news.sina.com.cn/';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
$html = curl_exec($ch);
curl_close($ch);
<p>// 提取标题(注意:新浪首页结构不稳定,正则需宽松)
preg_match_all('/<h1\s+data-client="headline">([^<]+)<\/h1>/iU', $html, $matches);
$titles = array_map('trim', $matches[1]);
print_r($titles);</p>- 必须加
CURLOPT_USERAGENT,否则多数时候拿不到 HTML -
CURLOPT_ENCODING要设成gzip,deflate,否则可能解压失败导致乱码 - 正则不能写死路径或 class 名,新浪经常微调 DOM 结构;优先匹配语义化属性(如
data-client)
编码问题怎么破?iconv 还是 mb_convert_encoding?
新浪首页目前是 UTF-8,但部分子页(尤其是旧新闻)仍是 GBK 编码。如果抓到中文乱码,别急着硬转,先确认源编码:
立即学习“PHP免费学习笔记(深入)”;
- 用
mb_detect_encoding($html)粗略判断(不绝对可靠) - 更稳的方式:看响应头
Content-Type中的charset=字段(curl_getinfo($ch, CURLINFO_CONTENT_TYPE)) - 若确定是 GBK → UTF-8,用
mb_convert_encoding($html, 'UTF-8', 'GBK')比iconv('gbk', 'utf-8', ...)更容错 - 避免在未检测前强行转码,否则可能把 UTF-8 当 GBK 转,产生“锟斤拷”
别只盯着标题:结构变动比你想的更频繁
新浪新闻首页不是静态页面,它用 JS 注入部分内容(尤其推荐位),纯服务端抓取拿到的是骨架 HTML,很多标题实际藏在异步接口里(比如 https://feed.mix.sina.com.cn/api/roll/get?...)。如果你发现 h1[data-client] 匹配不到预期数量,大概率是前端渲染了。
- 对策一:抓它的 JSON 接口(需分析 Network 面板,找
roll/get类请求) - 对策二:放弃首页,改抓频道页(如科技:
http://tech.sina.com.cn/),结构更稳定 - 对策三:加延迟、模拟滚动行为 —— PHP 做不到,得换 Puppeteer 或 Playwright
真正难的从来不是写几行 curl,而是应对它随时改 DOM、切接口、加反爬。别迷信“一次写完永久运行”。











