关于SO有四到五个问题可以解决这个特定的问题(一个例子);然而,它们都相当老了(超过10年),没有一个能充分解决具体问题。我希望这个问题的答案可以解决我的具体问题,同时为社区澄清困惑。
我正试图解析客户的网站,为他们的IT部门建立当前内容的摘要。(请不要问我为什么他们不能自己做。)
在过去,我使用PHP
库简单HTML DOM解析器来完成这样的任务。我已经有七年没有使用这个库了,但是我从来没有遇到过这个问题。
当使用…将文档加载到对象时
$dom = new DOMDocument('1.0','UTF-8');
$dom->loadHTMLFile($url); // run WITH error output
…PHP
沿着这一行返回警告:
警告:DOMDocument::loadHTMLFile(): htmlParseEntityRef: expected/myScript/index.php中的';'在https://thehtmlfilename.html,第45行第47行
警告:DOMDocument::loadHTMLFile(): htmlParseEntityRef: no name inhttps://thehtmlfilename.html,行:88在/myScript/index.php上行47
这些警告似乎既不能阻止加载DOM,也不能阻止脚本运行。但是,当我尝试使用$anchors = $dom->getElementsByTagName('a');
访问href
组时,脚本将运行前三个或四个(构造良好的)href,然后遇到如下一行:
<li class="">
<a href="https://www.thecompany.com/campus_staff.html">Campus & Staff</a>
</li>
<li class="">
<a href="https://www.thecompany.com/parents-and-families.html">Family & Friends</a>
</li>
仔细分析可以确定,正是这些行产生了上面的警告。这两行都产生了"期待";警告。
当我var_dump
$anchors
对象时,返回的全部内容是:
object(DOMNodeList)#2 (1) {
["length"]=>
int(90)
}
其他答案,如上面的链接问题,提到
我最好的猜测是有一个未转义的& (&)在HTML的某个地方。这将使解析器认为我们在实体参考(例如©)。当它到达;时,它认为实体是结束了。然后它意识到它所拥有的并不符合实体,所以它发出警告并以纯文本形式返回内容。
这表明我在正确的轨道上。
建议的各种解决方案都规定将&
更改为非&字符使用不同的方法:str_replace
,pre_replace
,htmlentities
, &等
&
字符似乎中断了由loadHTMLFile()
发起并创建DOM对象的加载过程。如果是这种情况,程序员无法在处理之前将&
字符replace
。
如何呢?识别问题是向前迈出的一大步,就像在关联问题中一样;但是我们如何解决这个问题呢?我们如何从这个页面拉这些href
链接?
值得注意的是,我们在…
中发现的&符号<a href="https://www.thecompany.com/campus_staff.html">Campus & Staff</a>
…不是在href本身,而是在链接文本中(在<a>
标签之间)。
首先以字符串形式获取内容,然后用可解析的内容替换&号实例。
$html = file_get_contents('/path/to/file.html');
$html = preg_replace('/&(?=s)/', '&', $html);
$doc = new DOMDocument();
$doc->loadHTML($html);
$anchors = $doc->getElementsByTagName('a');
foreach ($anchors as $anchor) {
print $anchor->firstChild->wholeText;
}