【问题标题】:PHP Regex preg_match_all div not same idPHP 正则表达式 preg_match_all div 不同的 id
【发布时间】:2014-08-08 03:52:38
【问题描述】:

我有一个这样的html页面

<!DOCTYPE html>
    <html>
        ....
        <body>
            <div class="list-news fl pt10 ">
                Blue
            </div>
            <div class="list-news fl pt10 alternative">
                Yellow
            </div>
             <div class="list-news fl pt10 ">
                Red
            </div>
            <div class="list-news fl pt10 alternative">
                Cyan
            </div>
            <div class="list-news fl pt10 ">
                Black
            </div>
            <div class="list-news fl pt10 alternative">
                White
            </div>
        </body>
    </html>

现在我将编写一个排序 php 代码来获取我需要的所有内容

preg_match_all('@<div class="list-news fl pt10 .*?">(.*?)<div class="list-news fl pt10 .*?">@s',$rs,$match);

这是结果

[1] => Array
(
    [0] => <div>Blue</div></div>
    [1] => <div>Red</div></div>
    [2] => <div>Black</div></div>
)

结果仅显示 div &lt;div class="list-news fl pt10 "&gt; 中的内容,而不显示 &lt;div class="list-news fl pt10 alternative"&gt; 中的内容我可以使用 str_replace 删除 alternative 类但如果不替换此字符串,如何获取每个 div 匹配类中的所有内容@ 987654327@?

感谢您的想法。

【问题讨论】:

  • 改用php DOM扩展并通过xpath搜索
  • 你的正则表达式,顺便说一句,直到结束 &lt;/div 才匹配,但会消耗下一个开口;这就是为什么它会互相跳过。

标签: php jquery html css regex


【解决方案1】:

DOM 方法(带有天真的contains

$dom = new DOMDocument();
@$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$query = <<<'EOD'
//div[
    contains(@class, 'list-news') and
    contains(@class, 'fl') and
    contains(@class, 'pt10')]
EOD;

$nodes = $xpath->query($query);

$results = array();

foreach ($nodes as $node) {
    $results[] = trim($node->textContent);

}
print_r($results);

一种正则表达式方法(带有幼稚模式)

preg_match_all('~<div class="list-news fl pt10\b[^>]+>\s*\K.*?(?=\s*</div>)~',
               $html, $matches);
print_r($matches[0]);

这两种方式有点幼稚,因为contains 不关心单词边界和类顺序,而正则表达式模式不关心 html 代码可能存在的不规则性。

您的模式不起作用的原因是您无法获得重叠匹配。由于第一次出现以&lt;div class="list-news... 结尾,因此下一次出现不能以已经匹配的相同&lt;div class="list-news... 开头。

将最后一个&lt;div class="list-news... 放入前瞻(?=...) (这只是一个检查,内容不是匹配结果的一部分) 可能是一种方法。但是,使用结束标记&lt;/div&gt; 更简单。

\K用于从匹配结果中删除所有在(左侧)之前匹配的内容。

一个很好的折衷办法是提取所有包含类属性的 div 标签,然后在提取和修剪文本内容之前使用正则表达式检查属性值是否真的是您想要的:

$dom = new DOMDocument();
@$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$query = '//div[@class]';

$nodes = $xpath->query($query);

$results = array();

foreach($nodes as $node) {
    if ( preg_match('~(?:\s|^)list-news\s+fl\s+pt10(?:\s|$)~',
                    $node->getAttribute('class')) )
        $results = trim($node->textContent);
}

或者没有XPath:

$dom = new DOMDocument();
@$dom->loadHTML($html);

$divs = $dom->getElementsByTagName('div');

$results = array();

foreach($divs as $node) {
    if ( $node->hasAttribute('class') &&
         preg_match('~(?:\s|^)list-news\s+fl\s+pt10(?:\s|$)~',
                    $node->getAttribute('class')) )
        $results = trim($node->textContent);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2013-02-12
    • 2016-08-08
    相关资源
    最近更新 更多