【问题标题】:The [documentElement] of DOMDocument has false content while [textContent] includes all the text of the pageDOMDocument 的 [documentElement] 包含虚假内容,而 [textContent] 包含页面的所有文本
【发布时间】:2018-04-03 02:55:18
【问题描述】:

我试图从 HTML 页面中选择内容。问题是DOMDocument($html) 的结果在其“[documentElement]”节点中没有元素。然而,HTML 页面的所有文本(不包括 HTML 标记)都在 [textContent] 内。 这就是我制作DOMDocument 对象的方式:

$doc = new DOMDocument();
libxml_use_internal_errors(true);
$html = file_get_contents("https://example.com");
$doc->loadHTML($html);

这是输出的对象:

DOMDocument Object (
[doctype]=> (object value omitted)
[implementation]=> (object value omitted)
[documentElement]=> (object value omitted)
[actualEncoding]=> utf-8
[encoding]=> utf-8
[xmlEncoding]=> utf-8
[standalone]=> 1
[xmlStandalone]=> 1
[version]=>
[xmlVersion]=>
[strictErrorChecking]=> 1
[documentURI]=>
[config]=>
[formatOutput]=>
[validateOnParse]=>
[resolveExternals]=>
[preserveWhiteSpace]=> 1
[recover]=>
[substituteEntities]=>
[nodeName]=> #document
[nodeValue]=>
[nodeType]=> 13
[parentNode]=>
[childNodes]=> (object value omitted)
[firstChild]=> (object value omitted)
[lastChild]=> (object value omitted)
[previousSibling]=>
[nextSibling]=>
[attributes]=>
[ownerDocument]=>
[namespaceURI]=>
[prefix]=>
[localName]=>
[baseURI]=>
[textContent]=> blah blah blah

这样我就不能遍历 HTML 的标签并选择特定的内容。甚至new DOMXpath($doc) 也不会返回有用的内容,我认为这是因为DOMXpath($doc) 取决于[documentElement] 对象的[documentElement] 节点。这是var_dump(new DOMXpath($doc));的输出

object(DOMXPath)#2 (1) { ["document"]=> string(22) "(object value omitted)" }

我尝试了 curlfile_get_contents 两种方法来获取 HTML 内容,并且确信 HTML 内容是正确的(我能够通过 print_r($html) 在 PHP 文件中复制 HTML 页面。另外,我已经在 StackOverflow 上阅读了几个答案,但无法解决问题。

【问题讨论】:

    标签: php html dom xpath web-scraping


    【解决方案1】:

    printr 和 DOMDocument 不是特别有用,信息在那里,但显示得不是很好((object value omitted) 是提示)。

    如果相反,您开始使用 DOMDocument 方法,saveHTMLsaveXML。他们将为您格式化实际内容... 如果你尝试

    $html = file_get_contents("https://example.com");
    $doc->loadHTML($html);
    echo "print_r()...";
    print_r($doc);
    echo "saveHTML()...";
    echo $doc->saveHTML();
    

    你应该看到区别了。

    需要指出的一点是,要从特定点(例如从 XPath 结果)输出,您使用

    echo $doc->saveHTML( $xpResultNode );
    

    编辑:使用更具体的代码:

    $doc = new DOMDocument();
    $html = file_get_contents("https://example.com");
    $doc->loadHTML($html);
    $xp = new DOMXpath($doc);
    $node = $xp->query('//*[@id="datacontainer"]/div[2]/table/tbody/tr[3]/td[4]/table/tr[2]/td');
    echo $doc->saveHTML($node[0]);
    

    我稍微修改了 XPath 查询,因为表的最后一级没有 tbody 标记。

    【讨论】:

    • 谢谢,关于你说的最后一个提示,所以不需要new DOMXpath($doc);?正如我在许多地方看到的那样,这是此过程中的必要步骤。 hereherehereherehere 和...。 This is the code I ran,但无法访问例如 HTML 中的 td
    • 非常感谢。请您编辑网站的 url 并将其更改为 example.com 好吗?所以你同意 DOMXpath 对象对于访问 html 标签的内容是强制性的吗?关于更改您提到的 XPath 查询,我只是使用 chrome 的开发人员工具复制了 XPath。为什么错了?
    • 更新了网址。 XPath 对于访问内容非常有用,我认为这正是我想指出的使用 this 的输出作为 saveHTML 的输入的重点。至于 XPath 声明 - Chrome 倾向于添加 TBODY 标签,因为它感觉像它。最好的方法是获取生成的实际 HTML(即来自file_get_contents)并使用它。我倾向于将它加载到 Eclipse(我的 ide)中,然后在其中尝试 XPath。
    • 我只是想知道人们如何在没有saveHTML()for 循环的情况下提取内容并遍历XPath 对象。喜欢this
    • 如果你只想要一个DOMNode的文本内容,你可以使用->nodeValue,或者你有时在XPath中使用evaluate而不是query(stackoverflow.com/questions/23793816/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 2011-04-05
    • 2013-02-20
    • 1970-01-01
    • 2021-04-21
    相关资源
    最近更新 更多