1

我正在尝试遵循使用 php进行网络抓取的教程。

我大致了解发生了什么,但我不知道如何过滤已抓取的内容以获得我想要的内容。例如:

<?php
$file_string = file_get_contents('page_to_scrape.html');
preg_match('/<title>(.*)<\/title>/i', $file_string, $title);
$title_out = $title[1];
?>

我看到(.*)将检索标题标签之间的所有内容,我可以使用正则表达式来获取特定信息。说里面他的标题有Welcome visitor #100我如何得到哈希后的数字?

还是我必须检索标签之间的所有内容,然后再对其进行操作?

4

3 回答 3

3

给定标题“Welcome visitor #100”以及<title>标签出现不超过一次的事实,表达式应该是:

preg_match('~<title>Welcome visitor #(\d+)</title>~', ...);

很多 SO 上的人会争辩说永远不要使用正则表达式来解析 (X)HTML;然而,对于这项任务,以上内容就足够了。

虽然 - 如前所述 -<title>标签(应该)出现不超过一次,但模式

<title>(.*)</title>

也可以匹配这个:

<title>Welcome visitor <title>#<title>100blafoobar</title>

(.*)作为允许这样做的部分。一旦您从更改中抓取数据的页面,正则表达式可能会停止工作。


编辑:一种正确筛选出多个元素及其属性的方法:

$dom = new DomDocument;
$dom->loadHTML($page_content);

$elements = $dom->getElementsByTagName('a');

for ($n = 0; $n < $elements->length; $n++) {
    $item = $elements->item($n);
    $href = $item->getAttribute('href');
}
于 2012-02-23T00:13:15.880 回答
2

您只需要更改正则表达式以匹配您需要的任何内容。如果您要多次使用该图块,最好保存整个图块并稍后对其进行操作,否则只需获得您需要的东西。

/<title>.*((?<=#)\d*).*<\/title>/i

将专门匹配哈希后的数字。它不会匹配没有哈希的数字。

编写正则表达式的方法有很多,这取决于您想要的通用性或特定性。

你也可以这样写来获得任何数字:

/<title>.*(\d)*.*<\/title>/i

于 2012-02-23T00:16:46.370 回答
0

我会首先获取标题标签,然后进一步处理标题。其他答案包含此任务的完全有效的解决方案。

一些进一步的说明:

  • 请为此类事情使用 DOMDocument,因为它更安全(您的正则表达式可能会在某些特定的 HTML 页面上中断)
  • .*请使用:的非贪婪版本.*?,否则你会遇到一些有趣的事情,例如:

    <html>
        <head>
            <title>a</title>
        </head>
        <body>
            <title>test</title> <!-- not allowed in HTML, but since when does the web pages online actually care about that? -->
        </body>
    </html>
    

您现在将匹配<title>a</title>...至 之间的<title>test</title>所有内容,包括介于两者之间的所有内容。

于 2012-02-23T16:22:06.103 回答