如何使用CURL解析页面中的实际HTML?

6

我正在尝试爬取一个网页,该网页内部有以下结构:

<p class="row">
    <span>stuff here</span>
    <a href="http://www.host.tld/file.html">Descriptive Link Text</a>
    <div>Link Description Here</div>
</p>

我正在使用curl来抓取网页:
<?php
    $handle = curl_init();
    curl_setopt($handle, CURLOPT_URL, "http://www.host.tld/");
    curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
    $html = curl_exec($handle);
    curl_close($handle);
?>

我做了一些研究,发现不应该使用正则表达式来解析从curl返回的HTML,而应该使用PHP DOM。这是我如何做到的:

$newDom = new domDocument;
$newDom->loadHTML($html);
$newDom->preserveWhiteSpace = false;
$sections = $newDom->getElementsByTagName('p');
$nodeNo = $sections->length;
for($i=0; $i<$nodeNo; $i++){
    $printString = $sections->item($i)->nodeValue;
    echo $printString . "<br>";
}

现在我并不是完全理解这个,但我大概明白了,并且我知道我需要的部分。唯一的问题是我得到的只是HTML页面的文本,就像我从浏览器窗口中复制出来的一样。我想要的是实际的HTML,因为我也想提取链接并使用它们,就像这样:

for($i=0; $i<$nodeNo; $i++){
    $printString = $sections->item($i)->nodeValue;
    echo "<a href=\"<extracted link>\">LINK</a> " . $printString . "<br>";
}

如您所见,我无法获取链接,因为我只获取到了网页的文本而非源代码,这不是我想要的。我知道 "curl_exec" 可以获取 HTML,因为我已经尝试过,所以我相信 DOM 在某种程度上剥离了我想要的 HTML。

3个回答

4
根据PHP手册上关于 DOM 的评论,您应该在循环内部使用以下代码:
    $tmp_dom = new DOMDocument();
    $tmp_dom->appendChild($tmp_dom->importNode($sections->item($i), true));
    $innerHTML = trim($tmp_dom->saveHTML()); 

这将设置$innerHTML为节点的HTML内容。
但我认为你真正想要的是获取'p'节点下的'a'节点,所以请执行以下操作:
$sections = $newDom->getElementsByTagName('p');
$nodeNo = $sections->length;
for($i=0; $i<$nodeNo; $i++) {
    $sec = $sections->item($i);
    $links = $sec->getElementsByTagName('a');
    $linkNo = $links->length;
    for ($j=0; $j<$linkNo; $j++) {
        $printString = $links->item($j)->nodeValue;
        echo $printString . "<br>";
    }
}

这将仅打印每个链接的正文。

您也可以使用foreach来迭代节点,而不是使用for循环。这将使代码更加简洁和易于理解,因为您似乎并不需要任何索引。 - janmoesen

1
你可以将节点传递给DOMDocument::saveXML()。尝试这样做: $printString = $newDom->saveXML($sections->item($i));

是的,这将有效地返回节点的 outerHTML - Gordon
显然,海报想要的是内部 HTML 而不是外部的。虽然对我来说不太清楚,但我仍然会保留我的答案以供 saveXML 参考。 - janmoesen

0

如果你想进行服务器端的HTML解析,可以考虑使用phpQuery。这里还有一个基本示例


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