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

Posted

技术标签:

【中文标题】如何使用 CURL 解析页面中的实际 HTML?【英文标题】:How to parse actual HTML from page using CURL? 【发布时间】:2011-03-25 11:14:14 【问题描述】:

我正在“尝试”抓取页面内具有以下结构的网页:

<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);
?>

我做了一些研究,发现我不应该使用 RegEx 来解析从 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。

【问题讨论】:

【参考方案1】:

根据the PHP manual on DOM 上的 cmets,您应该在循环中使用以下内容:

    $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 循环遍历节点。这将使它更加紧凑和易于理解,因为您实际上(似乎)不需要任何索引。【参考方案2】:

您可以将节点传递给DOMDocument::saveXML()。试试这个:

$printString = $newDom-&gt;saveXML($sections-&gt;item($i));

【讨论】:

是的,这将有效地返回节点的outerHTML 显然,发帖人想要的是内部的 HTML,而不是外部的。这对我来说并不清楚,但无论如何,我会将我的答案留给saveXML 参考。【参考方案3】:

您可能想看看 phpQuery 进行服务器端 HTML 解析。 basic example

【讨论】:

以上是关于如何使用 CURL 解析页面中的实际 HTML?的主要内容,如果未能解决你的问题,请参考以下文章

如何用php 编写网络爬虫?

使用 curl 时如何正确处理压缩页面?

如何分析curl抓取页面的编码

如何从 POCO websocket 服务器解析 html 页面?

如何用Curl 来post xml 数据

如何用Curl 来post xml 数据