PHP Regex,匹配具有条件的两个特定单词/标签之间的任何内容

时间:2013-07-26 18:06:49

标签: php regex html-parsing

我的正则表达式很差,这是我的情景,

我正在尝试从包含多个表的网页中提取一些信息,只有一些表包含一个唯一的URL(让我们说“very / unique.key”),所以它看起来像这样:

<table ....>
   (bunch of content)
</table>

<table ....>
   (bunch of content)
</table>

<table ....>
   (bunch of content + "very/unique.key" keyword)
</table>

<table ....>
   (bunch of content)
</table>

<table ....>
   (bunch of content + "very/unique.key" keyword)
</table>

所以我想要的是提取包含“very / unique.key”关键字的所有表的内容。以下是我尝试过的模式:

$pattern = "#<table[^>]+>((?!\<table)(?=very\/unique\.key).*)<\/table>#i";

这对我没有任何回报......

$pattern = "#<table[^>]+>((?!<table).*)<\/table>#i";

即使有<table...>条件,这也会从表1的开放标记</table>到最后一个表的结束标记(?!<table)返回所有内容...

感谢任何愿意帮助我的人,谢谢。

- 的修改 -

以下是我使用DOM循环遍历每个表的解决方案

- 我的解决方案 -

    $index;//indexes of all the table(s) that contains the keyword
        $cd = 0;//counter

        $DOM = new DOMDocument();
        $DOM->loadHTMLFile("http://uni.corp/sub/sub/target.php?key=123");
        $xpath = new DomXPath($DOM);
        $tables = $DOM->getElementsByTagName("table");
        for ($n = 0; $n < $tables->length; $n++) {
            $rows = $tables->item($n)->getElementsByTagName("tr");
            for ($i = 0; $i < $rows->length; $i++) {
                $cols = $rows->item($i)->getElementsbyTagName("td");
                for ($j = 0; $j < $cols->length; $j++) {


                     $td = $cols->item($j); // grab the td element
                     $img = $xpath->query('./img',$td)->item(0); // grab the first direct img child element


                    if(isset($img) ){
                        $image = $img->getAttribute('src'); // grab the source of the image
                        echo $image;
                        if($image == "very/unique.key"){
                            echo $cols->item($j)->nodeValue, "\t";
                            $index[$cd] = $n;
                            if($n > $cd){
                                $cd++;
                            }


                            echo $cd . " " . $n;//for troubleshooting
                        }


                    }

                }
                echo "<br/>";
            }
        }   

        //loop that echo out only the table(s) that I want which contains the keyword
        $loop = sizeof($index);
        for ($n = 0; $n < $loop; $n++) {
            $temp = $index[$n];
            $rows = $tables->item($temp)->getElementsbyTagName("tr");
            for ($i = 0; $i < $rows->length; $i++) {
                $cols = $rows->item($i)->getElementsbyTagName("td");                
                for ($j = 0; $j < $cols->length; $j++) {
                    echo $cols->item($j)->nodeValue, "\t";
                    //proccess the extracted table content here
                }
                //echo "<br/>";
            }
        }

但就个人而言,我仍然对Regex部分感到好奇,希望任何人都可以找到这个问题的正则表达式模式的解决方案。无论如何,感谢所有帮助/建议我的人(特别是对AbsoluteƵERØ)。

2 个答案:

答案 0 :(得分:2)

这适用于PHP5。我们解析表并使用preg_match()来检查密钥。您希望使用这样的方法的原因是因为HTML不必像XML那样在语法上正确编写。因此,您实际上可能没有正确的结束标记。此外,您可能有嵌套表,这将为您提供多个结果,尝试将开始和结束标记与REGEX匹配。这样我们只检查密钥本身,而不是正在解析的文档的好形式。

<?php

$input = "<html>
<table id='1'>
<tr>
<td>This does not contain the key.</td>
</tr>
</table>
<table id='2'>
<tr>
<td>This does contain the unique.key!</td>
</tr>
</table>

<table id='3'>
<tr>
<td>This also contains the unique.key.</td>
</tr>
</table>

</html>";

$html = new DOMDocument;
$html->loadHTML($input);

$findings = array();

$tables = $html->getElementsByTagName('table');
foreach($tables as $table){

    $element = $table->nodeValue;

    if(preg_match('!unique\.key!',$element)){
        $findings[] = $element;
    }
}

print_r($findings);

?>

<强>输出

Array
(
    [0] => This does contain the unique.key!
    [1] => This also contains the unique.key.
)

答案 1 :(得分:1)

虽然我同意你对帖子的评论,但我会给出解决方案。如果你想用其他东西替换这个/ unique.key,正确的正则表达式看起来像这样

#<table(.*)>((.*)very\/unique\.key(.*))<\/table>#imsU

这里的关键是使用正确的修饰符使其适用于您的输入字符串。有关这些修饰符的更多信息,请参阅http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

现在这里是一个例子,我用“foobar”替换了这个非常/ unique.key

<?php
$string = "
<table ....>
   (bunch of content)
</table>

<table ....>
   (bunch of content)
</table>

<table ....>
   bunch of content very/unique.key 
</table>

<table ....>
   (bunch of content)
</table>

<table ....>
   blabla very/unique.key
</table>
";

$pattern = '#<table(.*)>((.*)very\/unique\.key(.*))<\/table>#imsU';

echo preg_replace($pattern, '<table$1>$3foobar$4</table>', $string);
?>

此代码打印完全相同的字符串,但两个“very / unique.key”替换为“foobar”,就像我们想要的那样。

虽然这个解决方案可行,但它肯定不是效率最高,也不是最简单的方法。就像Mehdi在评论中所说的那样,PHP有一个专门用于操作XML(因此是HTML)的扩展。

以下是该扩展程序文档的链接 http://www.php.net/manual/en/intro.dom.php

使用它,您可以轻松浏览每个表元素并找到具有唯一键的元素。