如何在PHP中更优雅地解析html?

时间:2015-06-28 12:19:34

标签: php

简单的HTML代码就在这里。

<table>

<tr><th>Name</th><th>Price</th><th>Country</th></tr>
<tr><td><a href="bbb/111">Apple</a></td><td>500</td><td>America</td></tr>
<tr><td><a href="bbb/222">Samsung</a></td><td>400</td><td>Korea</td></tr>
<tr><td><a href="bbb/333">Nokia</a></td><td>300</td><td>Finland</td></tr>
<tr><td><a href="bbb/444">HTC</a></td><td>200</td><td>Taiwan</td></tr>
<tr><td><a href="bbb/555">Blackberry</a></td><td>100</td><td>America</td></tr>

</table>

我想要做的是废弃公司名称及其价格。像这样。

Apple 500 / Samsung 400 / Nokia 300 / HTC 200 / Blackberry 100 

所以,我使用php dom解析器。我知道有很多php解析器插件,但人们说最好使用原始的php解析器。所以我这样编码。

$source_n = file_get_contents($html);
$dom = new DOMDocument();
@$dom->loadHTML($source_n);
$stacks =  $dom->getElementsByTagName('table')->item(0)->textContent;
echo $stacks; 

它将显示许多字符串值....就像这样。

Name Price Country Apple 500 America Samsung 400 Korea ......

我认为,这不是有用的编码,如果我像上面那样编码,我应该使用explode()函数,并且代码将比现在更脏。

如何更优雅地报废? 有什么简单的参考吗?

3 个答案:

答案 0 :(得分:3)

使用DOMXPath::query,首先收集所有名称

$selector = new DOMXPath($dom);

$results = $selector->query('//td/a');

foreach($results as $node) {
    echo $node->nodeValue . PHP_EOL;
}

然后,通过改变

之后的价格
$results = $selector->query('//td[2]');

沙箱样本here

答案 1 :(得分:1)

我发现解析html的最佳解决方案是使用symfony's Dom crawler组件。与css选择器一起,您可以像在javascript中选择一个类一样过滤HTML。例如,要获取所有p元素,请执行:

$crawler = $crawler->filter('body > p');

答案 2 :(得分:0)

如果您不想使用DOMXPath::query

<?php 

$html = '<table>
            <tr><th>Name</th><th>Price</th><th>Country</th></tr>
            <tr><td><a href="bbb/111">Apple</a></td><td>500</td><td>America</td></tr>
            <tr><td><a href="bbb/222">Samsung</a></td><td>400</td><td>Korea</td></tr>
            <tr><td><a href="bbb/333">Nokia</a></td><td>300</td><td>Finland</td></tr>
            <tr><td><a href="bbb/444">HTC</a></td><td>200</td><td>Taiwan</td></tr>
            <tr><td><a href="bbb/555">Blackberry</a></td><td>100</td><td>America</td></tr>
        </table>';

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

//Get tables
$tables = $dom->getElementsByTagName('table');

//Get tr out of first table
$tableRows = $tables->item(0)->getElementsByTagName('tr');

//iterate over tablerows
foreach($tableRows AS $tableRow){

    //Get tableData
    $tableData = $tableRow->getElementsByTagName('td');  

    //check to see if there is tableData
    if($tableData->length >0){

        //Output first and second tableData
        echo $tableData->item(0)->nodeValue . " " . $tableData->item(1)->nodeValue . "<br>";

    }

}

?>