使用DOMDocument的网络爬虫

3
我正在尝试使用file_get_contents获取HTML并使用DOMDocument对象来提取网页内容。我的问题是我无法获得适当的信息。我不确定这是因为我错误地使用了DOMDocument的方法,还是源文件中的(X)HTML质量较差。
在源文件中,有一个id为'cards'的元素,它有两个子div。我想要第一个子元素,它有许多子div,而这些子元素又有一个带有div子元素的anchor子元素。我想要从anchor获取href和其子div的nodeValue。
结构如下:
<div id="cards">
    <div class="grid">
        <div class="card-wrap">
            <a href="linkValue">
                <img src="..."/>
                <div>nameValue</div>
            </a>
        </div>
        ...
   </div>
   <div id="...">
   </div>
</div>

我使用$cards = $dom->getElementById("cards")开始。我得到一个DOMText对象,一个DOMElement对象,一个DOMText对象,一个DOMElement对象和一个DOMText对象。然后,我使用$grid = $cards->childNodes->item(1)获取第一个DOMElement对象,它可能是.grid元素。然而,当我遍历$grid时,我使用:

foreach($grid->childNodes as $item){
    if($item->nodeName == "div"){
        echo $item->nodeName,' | ',$item->nodeValue,'<br>';
    }
}

我最终得到了一个页面,里面充满了“div | nameValue”,其中nameValue是嵌入式div的nodeValue,并且我无法定位锚点以获取它们的href值。
我在DOMDocument方面做错了什么明显的事情吗?或者这里可能有更多的事情发生了吗?
2个回答

3

从您的示例代码可以看出,if($item->nodeName == "div") 将会排除任何 <a> 标签。此外,我不认为 childNodes 允许递归迭代。

因此,要访问相关节点,您 可以 使用:

$children = $dom->getElementById("cards")->childNodes
                ->item(1)->childNodes->item(1)->childNodes;

然而,正如你所看到的,这非常混乱...介绍XPath:


我加了 if($item->nodeName == "div") 的判断,否则每隔一个请求就会输出 "text | nameValue",从而重复我的信息。我应该在这方面更清楚一些。我没想到这需要xpath,但我想学习它也是值得的... - sharf
我提供给你的代码是可行的,如果你不想使用xpath的话。虽然使用card-wrap也很容易选择...你有很多选择。使用vardump进行调试,你应该能够相当快地得到你想要的结果。如果这一切都说得通,请接受这个答案。 - Don Scott
抱歉还没接受,我想看看是否会有其他人参与讨论。我已经快速尝试了你提供的代码,但它没有给我应该得到的信息。我一直在使用vardump来弄清每个domdoc对象包含的内容...而我得到的结果并不是我预期的。我有一种感觉这可能与源不是有效的xhtml有关... - sharf

0

XPath方式:

$src = <<<EOS
<div id="cards">
    <div class="grid">
        <div class="card-wrap">
            <a href="linkValue">
                <img src="..."/>
                <div>nameValue</div>
            </a>
        </div>
   </div>
   <div id="whatever">
   </div>
</div>
EOS;

$xml = new SimpleXMLElement($src);

list ($anchor) = $xml->xpath('//div[@id="cards"]/div[1]/div[1]/a');
echo $anchor->div, ' => ', $anchor['href'], PHP_EOL;

"获取id为'cards'的div元素的第一个子div元素的锚点"

输出:

nameValue => linkValue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接