刮掉旧学校HTML - 不要以为我可以使用XPath / Dom,并且在regexp上生锈

时间:2013-07-09 19:31:20

标签: html dom preg-match web-scraping

这是我试图抓取的HTML片段:

    <div class="dot"><hr/></div>





    <h2>Description</h2>












        <p>This is the information I am trying to scrape</p>


</div>

我不认为我可以使用XPath来检索<p>的内容,因为它没有id或类,并且根据上面的其他信息,firebug提供的XPath可以是/html/body/div[3]/div/div[???]/p[2] - 哪里???是1-5之间的数字。

如果那是对的,那么我猜它回到了一个好的旧正则表达式(我没用过),不幸的是,这是我提出的最好的结果。尝试抓住它:

preg_match('/<h2>Description<\/h2>\s*<p>(.+)<\/p>/',$html,$rawdesc);

当然它不起作用......或者我不会辜负你的怜悯:)

4 个答案:

答案 0 :(得分:2)

Xpath或类似的DOM解析库,总是比解析html的正则表达式更好。除非您正在研究一个非常简单的一次性用例,否则确实没有例外。

如果您希望在p标记后直接匹配h2元素,请使用如下所示的xpath:

.//p[preceding-sibling::*[1][self::h2]]

我相信可以使用更简单的xpath查询,但这是我测试和验证的工作。

以下代码将为您提供所需的信息:

$dom = new DOMDocument();
$dom->loadHTML($yourHtmlString);
$xpath = new DOMXpath($dom);
$results = $xpath->query('.//p[preceding-sibling::*[1][self::h2]]');
$result = $results->item(0)->nodeValue;

答案 1 :(得分:0)

此模式有效:

preg_match('~<h2>Description</h2>\s*<p>\K(?>[^<]++|<++(?!/p>))+~', $html, $rawdesc);
print_r($rawdesc);

如果您在?

之后添加+,那么您也可以使用

答案 2 :(得分:0)

您似乎需要先将$html限制为包含说明的部分,例如

$start = strpos($html, '<h2>Description</h2>');
$end = strpos($html, '</div>', $start)
$html = substr($html, $start, $end-$start)

然后,您可以执行PeeHaa建议并使用<p>...</p>获取所有preg_match_all。然后使用implode合并它们。但也许我不明白你的问题。

答案 3 :(得分:0)

如果preg_match本身存在问题,您也可以尝试在模式中添加/ s开关,即preg_match('/<h2>Description<\/h2>\s*<p>(.+?)<\/p>/s',$html,$rawdesc);