preg_match与不同的标签

时间:2018-01-21 17:55:41

标签: php preg-match

我需要一些帮助。我试图从网站上删除一些指定数据。

<tbody>
    <tr style="mso-yfti-irow: 1;">
        <td style="width: 184.4pt; border: none; border-left: solid windowtext 1.5pt; padding: 0cm 5.4pt 0cm 5.4pt;" valign="top" width="307">
            <p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Certifikat springer 1000m</p>
        </td>

        <td style="width: 44.7pt; border: none; border-right: solid windowtext 1.5pt; padding: 0cm 5.4pt 0cm 5.4pt;" valign="top" width="75">
            <p class="MsoNormal" style="margin-bottom: .0001pt; text-align: right; line-height: normal;" align="right">90,-</p>
        </td>
    </tr>

    <tr style="mso-yfti-irow: 2;">
        <td style="width: 184.4pt; border: none; border-left: solid windowtext 1.5pt; padding: 0cm 5.4pt 0cm 5.4pt;" valign="top" width="307">
            <p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Certifikat springer 1200m</p>
        </td>

        <td style="width: 44.7pt; border: none; border-right: solid windowtext 1.5pt; padding: 0cm 5.4pt 0cm 5.4pt;" valign="top" width="75">
            <p class="MsoNormal" style="margin-bottom: .0001pt; text-align: right; line-height: normal;" align="right">100,-</p>
        </td>
    </tr>   
</tbody>

我想要的是获得&#34; Certifikat springer 1000&#34;来自mos-yfti-irow1和90, - 来自下一个TD。但我不想在这个输出中从mos-yfti-irow2获取数据。

我想建立一些人们可以比较我们体育团体与不同俱乐部的某些活动的价格。我真的不确定怎么做。

这就是我现在所拥有的,但却无法真正发挥作用

    <?php 

    $file_string = file_get_contents('http://www.mfkviborg.dk/index.php?    option=com_content&view=article&id=21&Itemid=151');

    preg_match_all('/<p class="MsoNormal" style="margin-bottom: .0001pt;(.*)">(.*)<\/p>/i', $file_string, $links);

    ?>

    <p><strong>Links:</strong> <em>(Name - Link)</em><br />
    <?php
    echo '<ol>';
    for($i = 0; $i < count($links[1]); $i++) {
        echo '<li>' . $links[2][$i] . ' - ' . $links[1][$i] . '</li>';
    }
    echo '</ol>';
    ?>
</p>

任何线索?

2 个答案:

答案 0 :(得分:2)

一些问题:

  • 除非您在正则表达式末尾指定.修饰符,否则s与换行符不匹配。所以应该加上。

  • .*是贪婪的,所以它会尽可能地匹配,包括一些中间</p>。它不应该这样做,所以添加?(在两种情况下)

不是问题,但仍值得改变:

  • 第一个捕获组可能没有为您提供有用的信息,因此请删除那里的括号。

  • .中的.0001被视为任何字符,因此您应该将其转义。一种方法是将其设为[.]

这为您提供了以下代码:

preg_match_all('/<p class="MsoNormal" style="margin-bottom: [.]0001pt;.*?">(.*?)<\/p>/is', 
             $file_string, $links);

使用DOM解析器

请注意,如果您的源HTML仅稍微更改(使用额外的间距或更改双引号或单引号,或交换属性的位置...),您将遇到问题,并调用以调整代码。

最好将DOMDocument界面与DOMXPath query一起使用。这是如何工作的:

$doc = new DOMDocument();
libxml_use_internal_errors(true);
    $doc->loadHTML($file_string, LIBXML_NOCDATA | LIBXML_NOWARNING | LIBXML_NOERROR );
libxml_use_internal_errors(false);
$xpath = new DOMXPath($doc);
$nodes = $xpath->query("//p[contains(@class, 'MsoNormal') and contains(@style, 'margin-bottom: .0001pt')]");
foreach ($nodes as $node) {
    echo $node->textContent . "\n";
}

您也可以使用loadHTML方法代替load方法,并将URL作为第一个参数传递。

后续

您在评论中要求trmso-yfti-irow属性中style进一步过滤输出:

$nodes = $xpath->query("//tr[contains(@style, 'mso-yfti-irow')]//p[contains(@class, 'MsoNormal') and contains(@style, 'margin-bottom: .0001pt')]");

答案 1 :(得分:0)

正如其他人所说,使用一个像样的解析器,例如, DOMDocument()

<?php
# set up the dom
$dom = new DOMDocument();
$dom->loadHTML($your_data_here, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);# | LIBXML_COMPACT | LIBXML_NOENT );

# set up the xpath
$xpath = new DOMXPath($dom);

foreach ($xpath->query("//tr[contains(@style, 'mso-yfti-irow: 1')]") as $row) {
    $text = $xpath->query("td/p/text()", $row);
    $certificate = $text[0]->nodeValue;
    $price = $text[1]->nodeValue;
    echo "$certificate | $price\n";
}
?>

这会产生示例字符串:

Certifikat springer 1000m | 90,-

代码段设置DOM并在之后使用xpath表达式查询,请参阅PHP.net上的文档。