PHP爬虫中文乱码需先确认网页真实编码:优先解析HTTP响应头Content-Type中的charset,其次才是HTML的meta标签;转换时用mb_convert_encoding或iconv并指定准确编码名(如CP936而非gbk),必要时加//IGNORE;DOMDocument加载前须确保HTML为UTF-8并添加<meta charset="UTF-8">声明。

PHP爬虫抓到的中文是乱码?先看网页真实编码
乱码不是PHP的问题,而是你没拿到网页声明的编码。很多新手直接用 file_get_contents() 或 curl_exec() 拿回内容就硬解,结果 iconv() 或 mb_convert_encoding() 越转越糊。
真实编码藏在 HTTP 响应头的 Content-Type 里(比如 text/html; charset=utf-8),其次才是 HTML 中的 <meta charset="gbk"> 或 <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> —— 后者可能被页面作者写错,优先级低于响应头。
- 用
curl_getinfo($ch, CURLINFO_CONTENT_TYPE)提取响应头里的 charset - 如果没声明 charset,再解析 HTML 的
<meta>标签(建议用DOMDocument或正则/charset=["']?([^"'>]+)/i) - 坚决别默认用
UTF-8强解 GBK 页面,会出和截断
mb_convert_encoding() 转换失败?检查源编码是否识别准确
mb_convert_encoding($html, 'UTF-8', 'GBK') 报错或输出空,大概率是你传的源编码名不对。PHP 的 mbstring 对编码名很敏感:写 gbk 可能不认,得写 CP936;gb2312 有时要写成 GB2312-80;而 Big5 在部分环境得写 Big5-HKSCS。
更稳妥的做法是让 PHP 自动探测:mb_detect_encoding($html, ['UTF-8', 'GB2312', 'GBK', 'BIG5'], true) —— 注意第三个参数必须为 true,否则遇到混合编码会瞎猜。
立即学习“PHP免费学习笔记(深入)”;
- 探测结果不可全信,尤其当 HTML 前几KB全是英文时,
mb_detect_encoding()容易误判为ASCII - 若已知目标站固定用 GBK(如某些政府旧站),跳过探测,直接指定
CP936 - 转换后用
mb_check_encoding($result, 'UTF-8')验证,避免静默失败
iconv() 报 “Illegal character”?改用 //IGNORE 或 //TRANSLIT
iconv('GBK', 'UTF-8', $html) 遇到无法映射的字符(比如生僻汉字、旧版 GBK 扩展字),默认直接报错并中断。这不是 bug,是它的设计逻辑。
加 //IGNORE 丢弃非法字符,或 //TRANSLIT 尝试音译(如 “?” → “Ji”),就能继续跑。但要注意://IGNORE 可能删掉半个汉字导致后续 DOM 解析错位。
- 推荐组合写法:
iconv('GBK', 'UTF-8//IGNORE', $html) - 别用
//TRANSLIT处理新闻/政务类文本,音译会破坏原意 - 如果发现转换后中文变少,大概率是
//IGNORE删了字,此时应回退到mb_convert_encoding()+ 显式编码名
DOMDocument 加载乱码 HTML?先转码再加载
直接 $dom->loadHTML($html) 乱码,是因为 DOMDocument::loadHTML() 默认按 ISO-8859-1 解析。即使你传的是 UTF-8 字符串,它也会当 Latin1 处理,导致节点文本全崩。
解决方法很简单:在 loadHTML() 前,把整段 HTML 包一层 UTF-8 声明,并确保字符串本身已是 UTF-8:
$html = mb_convert_encoding($html, 'UTF-8', $detected_charset); $html = '<meta charset="UTF-8">' . $html; $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
- 必须用
LIBXML_HTML_NOIMPLIED,否则DOMDocument会自动补<html><body>,干扰原始结构 - 别依赖
loadHTMLFile(),它绕不开文件系统编码,本地测试容易因编辑器保存格式再次出错 - 如果目标页有 JS 动态插入内容,DOM 解析前的乱码问题再怎么修也没用——该上 Puppeteer 或 Playwright



















