【问题标题】:how to parse this by simple html dom parser in php如何通过简单的 html dom 解析器在 php 中解析它
【发布时间】:2012-11-14 22:50:03
【问题描述】:
<div id="productDetails" class="tabContent active details">
<span>
<b>Case Size:</b>
</span>
44mm
<br>

<span>
<b>Case Thickness:</b>
</span>
13mm
<br>

<span>
<b>Water Resistant:</b>
</span>
5 ATM
<br>

<span>
<b>Brand:</b>
</span>
Fossil
<br>

<span>
<b>Warranty:</b>
</span>
11-year limited
<br>

<span>
<b>Origin:</b>
</span>
Imported
<br>


</div>

如何通过 PHP 中的 DOM 解析器获取 44mm、化石等数据?

我可以轻松获取的数据

$data=$html-&gt;find('div#productDetails',0)-&gt;innertext;

var_dump($data);

但我想在我的 sql 表的 meta_key 和 meta_value 中打破它... 我可以通过

获得meta_key

$meta_key=$html-&gt;find('div#productDetails span',0)-&gt;innertext;

但是和它相关的元值????

【问题讨论】:

  • 你可以使用 Zend_Dom。它非常好,您可以使用 jquery 中的选择器。这是link
  • 我试过这个 $data=$html->find('/span/br'); $data=explode("\n", $data[0]->plaintext); var_dump(trim($data[0]));
  • 你是怎么解析 dom的,你为什么用正则表达式,即使你解析了dom,只是遍历它
  • 通过遍历我得到的输出为空。

标签: php dom html-parsing


【解决方案1】:

没那么难,真的...just google, and click this link,你现在知道如何解析 DOM,here 你可以看到可以使用哪些方法来选择所有感兴趣的元素,迭代 DOM,获取其内容你有什么...

$DOM = new DOMDocument();
$DOM->loadHTML($htmlString);
$spans = $DOM->getElementsByTagName('span');
for ($i=0, $j = count($spans); $i < $j; $i++)
{
    echo $spans[$i]->childNodes[0]->nodeValue.' - '.$spans[$i]->parentNode->nodeValue."\n";
}

如果我没记错的话,这似乎就是你所追求的。这只是我的想法,但我认为这应该输出如下内容:

Case Size: - 44mm
Case Thickness: - 13mm

更新:
这是一个经过测试的解决方案,如果我没记错的话,它会返回所需的结果:

$str = "<div id='productDetails' class='tabContent active details'>
            <span>
                <b>Case Size:</b>
            </span>
            44mm
                        <br>

            <span>
                <b>Case Thickness:</b>
            </span>
            13mm
                        <br>

            <span>
                <b>Water Resistant:</b>
            </span>
            5 ATM
                        <br>

            <span>
                <b>Brand:</b>
            </span>
            Fossil
                        <br>

            <span>
                <b>Warranty:</b>
            </span>
            11-year limited
                        <br>

            <span>
                <b>Origin:</b>
            </span>
            Imported
                        <br>
    </div>";
$DOM = new DOMDocument();
$DOM->loadHTML($str);
$txt = implode('',explode("\n",$DOM->textContent));
preg_match_all('/([a-z0-9].*?\:).*?([0-9a-z]+)/im',$txt,$matches);
//or if you don't want to include the colon in your match:
preg_match_all('/([a-z0-9][^:]*).*?([0-9a-z]+)/im',$txt,$matches);
for($i = 0, $j = count($matches[1]);$i<$j;$i++)
{
    $matches[1][$i] = preg_replace('/\s+/',' ',$matches[1][$i]);
    $matches[2][$i] = preg_replace('/\s+/',' ',$matches[2][$i]);
}
$result = array_combine($matches[1],$matches[2]);
var_dump($result);
//result:
array(6) {
    ["Case Size:"]=> "44mm"
    ["Case Thickness:"]=> "13mm"
    ["Water Resistant:"]=> "5"
    ["ATM Brand:"]=> "Fossil"
    ["Warranty:"]=> "11"
    ["year limited Origin:"]=> "Imported"
}

要将其插入您的数据库:

foreach($result as $key => $value)
{
    $stmt = $pdo->prepare('INSERT INTO your_db.your_table (meta_key, meta_value) VALUES (:key, :value)');
    $stmt->execute(array('key' => $key, 'value' => $value);
}

编辑
要完全捕获11-year limit 子字符串,您需要像这样编辑上面的代码:

//replace $txt = implode('',explode("\n",$DOM->textContent));etc... by:
$txt = $DOM->textContent;//leave line-feeds
preg_match_all('/([a-z0-9][^:]*)[^a-z0-9]*([a-z0-9][^\n]+)/im',$txt,$matches);
for($i = 0, $j = count($matches[1]);$i<$j;$i++)
{
    $matches[1][$i] = preg_replace('/\s+/',' ',$matches[1][$i]);
    $matches[2][$i] = preg_replace('/\s+/',' ',$matches[2][$i]);
}
$matches[2] = array_map('trim',$matches[2]);//remove trailing spaces
$result = array_combine($matches[1],$matches[2]);
var_dump($result);

输出是:

array(6) {
  ["Case Size"]=> "44mm"
  ["Case Thickness"]=> "13mm"
  ["Water Resistant"]=> "5 ATM"
  ["Brand"]=> "Fossil"
  ["Warranty"]=> "11-year limited"
  ["Origin"]=> "Imported"
}

【讨论】:

  • 好吧,我看到了这一切,但我无法清楚地理解……希望这次我能。
  • @down-voter:只要我知道原因,我不介意投反对票。谁知道呢,我可能会在此过程中学到一两件事
  • 我可以通过简单的方式获取该数据: $data=$html->find('div#productDetails',0)->innertext;但我想将数据分解为 mysql 表的 meta_key 和 meta_value
  • @rituraj,如果你愿意,请叫我粗一点,但我说的对吗?用冒号分隔键和值,用换行符分隔键值对?
  • @ellas:谢谢哥们...以后会打扰你的,,;-)
【解决方案2】:

您可以使用 set_callback Api 移除 span 标签

试试这个

$url = "";

$html = new simple_html_dom();
$html->load_file($url);
$html->set_callback('my_callback');

$elem = $html->find('div[id=productDetails]');

$product_details = array();
$attrib = array( 1 => 'size', 2 => 'thickness', 3 => 'wr', 4 => 'brand', 5 => 'warranty', 6 => 'orgin' );

$attrib_string = strip_tags($elem[0]->innertext);
$attrib_arr = explode('        ',$attrib_string); // hope this can help you for every product 
// Remove Empty Values
$attrib_arr = array_filter($attrib_arr);

$i = 1;
foreach($attrib_arr as $temp)
{
   $product_details[$attrib[$i]] = $temp;
$i++;
}

print_r($product_details);

// remove span tag inside div
function my_callback($element) {
if($element->tag == 'span'){  $element->outertext = ""; }
} 

【讨论】:

  • 我编辑了我的代码,您需要确保 Everytime explode() 函数适用于每个产品
猜你喜欢
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 2016-07-30
  • 2011-08-27
相关资源
最近更新 更多