脚本标记中的Symfony dom爬网程序字符串转换为UTF8


Symfony dom-crawler string in script tag convert to UTF8

我有以下HTML内容:

<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('测试');
    }
</script>

当我使用Symfony的dom爬网程序时,文本是HTML编码的。我该如何防止这种情况发生?$crawler->html()结果:

<div>测试</div>
<script>
    function drawCharts(){
        console.log('&#27979;&#35797;');
    }

让我们看看symfony/dom爬网程序是如何工作的。下面是一个例子:

<?php
require 'vendor/autoload.php';
use Symfony'Component'DomCrawler'Crawler;
$html = <<<HTML
<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('测试');
    }
</script>
HTML;
$crawler = new Crawler($html);
print $crawler->html();

它输出:

<div>æµè¯</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('&aelig;&micro;&#139;&egrave;&macr;&#149;');
    }
</script>

当您通过构造函数传递内容时,Crawler类会尽其所能找出编码。如果它什么都想不出来,它就回到ISO-8859-1;这是HTTP 1.1规范定义的默认字符集。

如果您的HTML内容包含一个字符集元标记,Crawler类将从中读取字符集,对其进行设置并从中正确转换。下面是上面的相同示例,在HTML内容前面加了一个字符集元标记:

<?php
require 'vendor/autoload.php';
use Symfony'Component'DomCrawler'Crawler;
$html = <<<HTML
<meta charset="utf-8">
<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('测试');
    }
</script>
HTML;
$crawler = new Crawler($html);
print $crawler->html();

现在它打印:

<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('&#27979;&#35797;');
    }
</script>

如果您不想添加charset元标记,还有另一种方法;addHTMLContent()方法接受一个字符集作为它的第二个参数,并且它默认为UTF-8。与其通过构造函数传递HTML内容,不如先实例化类,然后使用以下方法添加内容:

<?php
require 'vendor/autoload.php';
use Symfony'Component'DomCrawler'Crawler;
$html = <<<HTML
<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('测试');
    }
</script>
HTML;
$crawler = new Crawler;
// You can safely drop the 2nd argument
$crawler->addHTMLContent($html, 'UTF-8');     
print $crawler->html();

现在,在没有字符集元标签的情况下,它会打印:

<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('&#27979;&#35797;');
    }
</script>

好吧,你可能已经知道这一切了。那么,&#27979;&#35797;是怎么回事呢?为什么div内容按原样显示,但script标签中的相同内容正在进行html编码?

Symfony的Crawler类,正如它自己解释的那样,由于DOMDocument::loadHTML():中的一个错误,将内容转换为HTML实体

使用loadHTML()处理UTF-8页面时,可能会遇到DOM函数的输出与输入不一样的问题。例如,如果你想得到"Cạ"nh-tranh",您将收到"Cáºnh-tran"。我建议在加载UTF-8页面之前使用mb_convert_encoding
–https://php.net/manual/en/domdocument.loadhtml.php#74777

有些人建议在head元素中添加HTML4Content-Type元标记。其他一些人建议,在将HTML内容传递给loadHTML()之前,先在其前面加上<?xml encoding="UTF-8">。由于您的HTML结构不完整(缺少headbody等),我建议您简单地将输出传递给html_entity_decode():

<?php
require 'vendor/autoload.php';
use Symfony'Component'DomCrawler'Crawler;
$html = <<<HTML
<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('测试');
    }
</script>
HTML;
$crawler = new Crawler();
$crawler->addHTMLContent($html, 'UTF-8');
print html_entity_decode($crawler->html());

输出:

<div>测试</div>
<script charset="utf-8" type="text/javascript">
    function drawCharts(){
        console.log('测试');
    }
</script>

这就是你想要的。

您可能还想阅读:
PHP DOMDocument加载HTML未正确编码UTF-8