You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决PHP中DomDocument导致的文本乱码问题?

解决DOMDocument处理UTF-8特殊字符乱码问题

你的代码出现乱码的核心原因是DOMDocument默认使用ISO-8859-1编码解析HTML,而你的文本是UTF-8格式,导致特殊字符(如→、’)被错误转换。另外代码中还有一个逻辑错误:return语句放在了foreach循环内部,会导致只处理第一个链接就终止。

以下是具体修复方案:

1. 加载HTML时指定UTF-8编码

在加载原始HTML前,添加UTF-8编码声明,让DOMDocument正确识别编码:

$domDocument = new \DOMDocument();
// 前置UTF-8编码声明,避免DOMDocument默认用ISO-8859-1解析
$domDocument->loadHTML('<?xml encoding="UTF-8">' . $text, LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR);
$domDocument->formatOutput = true;
$links = $domDocument->getElementsByTagName('a');

2. 修复循环内的return语句

将return $domDocument->saveHTML();移到foreach循环外部,确保所有链接都被处理:

foreach($links as $link)
{
    $href = $link->getAttribute('href');
    $title = $this->fetchPageTitle($href);
    $link->nodeValue = $title;
}
// 循环结束后再返回处理后的HTML
$html = $domDocument->saveHTML();

3. 保存HTML时强制UTF-8编码

DOMDocument的saveHTML()默认可能输出ISO-8859-1编码的内容,需要转换为UTF-8:

return mb_convert_encoding($html, 'UTF-8', 'ISO-8859-1');

4. 优化页面标题获取的编码处理

在fetchPageTitle方法中,先根据响应头的字符集转换页面内容为UTF-8,再加载到DOMDocument:

private function fetchPageTitle($url) :string
{
    $response = Http::get($url);
    // 从响应头提取字符集,默认UTF-8
    $contentType = $response->header('Content-Type');
    $charset = 'UTF-8';
    if (preg_match('/charset=([^\s;]+)/', $contentType, $matches)) {
        $charset = $matches[1];
    }
    // 将页面内容转换为UTF-8
    $page_html = mb_convert_encoding($response->body(), 'UTF-8', $charset);
    
    $pageDocument = new \DOMDocument();
    // 同样添加UTF-8声明
    $pageDocument->loadHTML('<?xml encoding="UTF-8">' . $page_html, LIBXML_NOERROR);
    $titleNode = $pageDocument->getElementsByTagName('title')->item(0);
    // 处理标题不存在的情况,避免报错
    return $titleNode ? $titleNode->nodeValue : $url;
}

完整修正后的代码

$domDocument = new \DOMDocument();
$domDocument->loadHTML('<?xml encoding="UTF-8">' . $text, LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR);
$domDocument->formatOutput = true;
$links = $domDocument->getElementsByTagName('a');

foreach($links as $link)
{
    $href = $link->getAttribute('href');
    $title = $this->fetchPageTitle($href);
    $link->nodeValue = $title;
}

$html = $domDocument->saveHTML();
return mb_convert_encoding($html, 'UTF-8', 'ISO-8859-1');

private function fetchPageTitle($url) :string
{
    $response = Http::get($url);
    $contentType = $response->header('Content-Type');
    $charset = 'UTF-8';
    if (preg_match('/charset=([^\s;]+)/', $contentType, $matches)) {
        $charset = $matches[1];
    }
    $page_html = mb_convert_encoding($response->body(), 'UTF-8', $charset);
    
    $pageDocument = new \DOMDocument();
    $pageDocument->loadHTML('<?xml encoding="UTF-8">' . $page_html, LIBXML_NOERROR);
    $titleNode = $pageDocument->getElementsByTagName('title')->item(0);
    return $titleNode ? $titleNode->nodeValue : $url;
}

这些修改确保了整个流程中所有文本都以UTF-8编码处理,彻底解决特殊字符乱码问题,同时修复了只处理单个链接的逻辑错误。

内容的提问来源于stack exchange,提问作者TheBigK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:43:23