【问题标题】:How to get string from HTML with regex?如何使用正则表达式从 HTML 中获取字符串?
【发布时间】:2011-03-18 22:01:42
【问题描述】:

我正在尝试从 html 页面解析块,所以我尝试使用 php 来 preg_match 这个块

if( preg_match('<\/div>(.*?)<div class="adsdiv">', $data, $t)) 

但不起作用

</div>

blablabla

blablabla

blablabla

<div class="adsdiv">

我只想要 grep blablabla blablabla 单词 任何帮助

【问题讨论】:

  • 请准确描述您想要匹配的 html 文本?

标签: php regex html-parsing


【解决方案1】:

Regex aint the right tool for this。这是使用 DOM 的方法

$html = <<< HTML
<div class="parent">
    <div>
        <p>previous div<p>
    </div>
    blablabla
    blablabla
    blablabla
    <div class="adsdiv">
        <p>other content</p>
    </div>
</div>
HTML;

HTML 文档中的内容是 TextNodes。标签是元素节点。具有 blablabla 内容的 TextNode 必须有一个父节点。为了获取 TextNode 值,我们假设您想要 div 的 ParentNode 的所有 TextNode 以及 adsdiv 的 class 属性

$dom = new DOMDocument;
$dom->loadHTML($html);
$xPath = new DOMXPath($dom);
$nodes = $xPath->query('//div[@class="adsdiv"]');
foreach($nodes as $node) {
    foreach($node->parentNode->childNodes as $child) {
        if($child instanceof DOMText) {
            echo $child->nodeValue;
        }
    };
}

是的,它不是一个时髦的单行,但它也少了很多令人头疼的问题,并且让您可以可靠地控制 HTML 文档。利用 XPath 的查询能力,我们可以将上述内容缩短为

$nodes = $xPath->query('//div[@class="adsdiv"]/../text()');
foreach($nodes as $node) {
    echo $node->nodeValue;
}

我故意把它写得很详细来说明如何使用 DOM。

【讨论】:

    【解决方案2】:

    除了上面所说的之外,还要添加/s 修饰符,以便. 将匹配换行符。 (编辑:正如 Alan 指出的那样,[^&lt;]+ 无论如何都会匹配换行符)

    我也总是使用/U,因为在这些情况下,您通常需要默认的最小匹配。 (也会更快)。还有/i,因为人们说&lt;div&gt;、&lt;DIV&gt;,甚至&lt;Div&gt;...

    if (preg_match('/<\/div>([^<]+)<div class="adsdiv">/Usi', $data, $match))
    {
        echo "Found: ".$match[1]."<br>";
    } else {
        echo "Not found<br>";
    }
    

    编辑让它更明确一点!

    【讨论】:

    • 感谢 mvds 的回复,但它以空结果回复意味着不起作用
    • 好的,我添加了一个小代码,展示了如何从中获取匹配的部分。这应该可以工作(尽管它要求输入完全您正在显示的内容;即不是类似firefox的“查看源代码”格式化的html!)
    • [^&lt;] 将匹配换行符,无论您是否使用 /s 修饰符。
    • 我建议不要养成使用 /U 修饰符的习惯。最好改掉使用.*的习惯。不情愿的量词通过避免过度回溯来加速匹配,但您已经通过使用 [^&lt;]+ 而不是 .* 来处理这一点。如果有的话,/U 会减慢您的速度,因为逐字符、不情愿的量词比贪婪的量词慢。
    【解决方案3】:

    来自PHP Manual:

    s (PCRE_DOTALL) - 如果设置了此修饰符,则 模式匹配所有字符, 包括换行符。没有它, 换行符被排除在外。这个修饰符 相当于 Perl 的 /s 修饰符。一种 负类,例如 [^a] 总是 匹配换行符, 独立于此的设置 修饰符。

    所以,以下应该可以工作:

    if (preg_match('~<\/div>(.*?)<div class="adsdiv">~s', $data, $t))
    

    ~ 用于分隔正则表达式。

    【讨论】:

      【解决方案4】:

      您需要对正则表达式进行分隔;请改用/&lt;\/div&gt;(.*?)&lt;div class="adsdiv"&gt;/。

      【讨论】:

      • 虽然没有解决OP的问题,但这是的一个有效点。问题中的正则表达式缺少分隔符,如果您尝试使用它会引发异常。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 2014-09-23
      • 1970-01-01
      相关资源
      最近更新 更多