DOMDocument :: loadHTML():由于输入错误,输入转换失败

时间:2014-04-29 09:14:41

标签: php parsing dom curl web-scraping

我希望使用 PHP CURL 废弃中文网站。早些时候我遇到了压缩结果的问题,SO帮助我解决了问题。 现在,我在通过 PHP - DOMDocument 解析内容时遇到了麻烦。 错误如下,

Warning: DOMDocument::loadHTML(): input conversion failed due to input error, bytes 0xE3 0x80 0x90 0xE8 in /var/www/html/ ..

即使发出警告,也无法获得进一步的结果。

我的代码如下:

$agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0';
$curl = curl_init(); 
curl_setopt($curl, CURLOPT_URL,$url); 
curl_setopt($curl, CURLOPT_HTTPHEADER, array('text/html; charset=gb2312')); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);  
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($curl, CURLOPT_ENCODING, "");  // handling all compressions 
curl_setopt($curl, CURLOPT_USERAGENT, $agent);
curl_setopt($curl, CURLOPT_TIMEOUT, 1000);
$html = curl_exec($curl) or die("error: ".curl_error($curl));
curl_close($curl);
$htmlParsed = mb_convert_encoding($result,'utf-8','gb2312');

$doc = new DOMDocument();
$doc->loadHTML($htmlParsed);

$xpath = new DOMXpath($doc);

$elements = $xpath->query('//div[@class="test"]//a/@href');

if (!is_null($elements)) {
  foreach ($elements as $element) {
    echo "<br/>[". $element->nodeName. "]";

    $nodes = $element->childNodes;
    foreach ($nodes as $node) {
      echo $node->nodeValue. "\n";
    }
  }
}

我在目标网站中找到了内容类型,

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

所以我尝试将结果转换为utf-8。

由于输入转换在&#39; DOMDocument :: loadHTML()&#39;代码行,我无法解析网页以获得结果。 我目前陷入困境,任何帮助或建议都将受到高度赞赏。提前完成。

(之前我曾经使用过简单的HTML DOM解析器,这非常简单。但之后在SO中阅读有关其用法的缺点。我计划切换到PHP的原生DOM解析器)< / em>的

3 个答案:

答案 0 :(得分:3)

我今天看到了一个解决方案。

$html=new DOMDocument();  
$html_source    = get_html();
$html_source    =mb_convert_encoding( $html_source, "HTML-ENTITIES", "UTF-8");
$html->loadHTML( $html_source );

答案 1 :(得分:2)

如果没有看到您要解析的文档的完整头部我只能猜测,但如果带有字符编码数据的文件没有直接在标记之后,您可能会遇到DomDocument正在使用其默认值的情况ISO-8859-1并且运行到【字符(gb2312中的前三个“无效”字节),其中0x80字节将是无意义的第一位,因为这是ISO-8859-1中未使用的代码点。这可能会触发上面评论中讨论的DomDocument中的错误。如果元素包含在内容类型元信息之前,则很容易发生。

我唯一能想到的尝试就是通过一些准备运行html并将该内容类型的元标记移到标签后面,以尝试使其使用正确的字符集。如果使用mb_convert_encoding或iconv将编码转换为iso-5589-1或utf-8,请确保修改元信息,因为不幸的是,DomDocument在很多方面都很脆弱。

答案 2 :(得分:2)

<?php
$contents = file_get_contents('xml.xml');
function convert_utf8( $string ) { 
    if ( strlen(utf8_decode($string)) == strlen($string) ) {   
        // $string is not UTF-8
        return iconv("ISO-8859-1", "UTF-8", $string);
    } else {
        // already UTF-8
        return $string;
    }
}

$contents = mb_convert_encoding( $contents, mb_detect_encoding($contents), "UTF-8");

$xml = simplexml_load_string(convert_utf8($contents));
print_r($xml);