2017-03-01 151 views
4

我有这个PHP DOM网络爬虫,它工作正常。它提取提及的标签以及从(外部)论坛站点到我的页面的链接。使用DOM从外部网站选择性提取数据PHP网络爬虫

但最近我遇到了一个问题。像

这是论坛数据的HTML ::

<tbody> 
<tr> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="64%" height="25" class="FootNotes2"><a href="/files/forum/2017/1/837880.php" target="_top" class="Links2">Hispanic Study Partner</a> - dreamer1984</td> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="14%" height="25" class="FootNotes2" align="center">02/28/17 01:42</td> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="8%" height="25" align="Center" class="FootNotes2">0</td> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="9%" height="25" align="Center" class="FootNotes2">200</td> 
</tr> 
<tr> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="64%" height="25" class="FootNotes2"><a href="/files/forum/2017/1/837879.php" target="_top" class="Links2">nbme</a> - monariyadh</td> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="14%" height="25" class="FootNotes2" align="center">02/27/17 23:12</td> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="8%" height="25" align="Center" class="FootNotes2">0</td> 
    <td width="1%" height="25">&nbsp;</td> 
    <td width="9%" height="25" align="Center" class="FootNotes2">108</td> 
</tr> 
</tbody> 

现在,如果我们考虑到上面的代码(表数据)在网站上提供的唯一语句。如果我试图用一个网络爬虫一样提取它,

<?php 
    require_once('dom/simple_html_dom.php'); 
    $html = file_get_html('http://www.sitename.com/'); 
    foreach($html->find('td.FootNotes2') as $element) { 
    echo $element; 
} 
?> 

它提取人与类名是内显示为“FootNote2”数据

现在,如果我想提取特定数据标签,例如第一个标签/行中的名称,如“dreamer1984”和“monariyadh”。

以及如果我想从第3个数据中提取数据(跳过其余的),它具有相同的类名称。

请注意,我可以使用“正则表达式”像

preg_match_all('/<td.+?FootNotes2.+?<a.+?<\/a> - (?P<name>.*?)<\/td>.+?<td.+?FootNotes2.+?(?P<date>\d{2}\/\d{2}\/\d{2} \d{2}:\d{2})/siu', $subject, $matchs); 

foreach ($matchs['name'] as $k => $v){ 
    var_dump('name: '. $v, 'relative date: '. $matchs['date'][$k]); 
} 

但我更喜欢找到DOM解析器这种解决方案 任何帮助表示赞赏..

+2

可能的重复[使用DOM PHP Web爬虫从论坛网站中选择数据提取](http://stackoverflow.com/questions/42511008/selective-data-extraction-from-forum-site-using-dom-php-网络爬虫) –

+0

某些文本解析将是必要的(例如,通过正则表达式)我不认为你可以避免这种情况。您可以做的最好的做法是将正则表达式位限制为td元素的文本内容。 – apokryfos

+0

@harishk检查我的答案是你想要什么? –

回答

2

正如我在说我的评论一些文字处理是不可避免的,但你可以得到与TD像这样相关的文本元素:

require_once('dom/simple_html_dom.php'); 
$html = file_get_html('http://www.sitename.com/'); 
foreach ($html->find("tr") as $row) { 
     $element = $row->find('td.FootNotes2',0); 
     if ($element == null) { continue; } 
     $textNode = array_filter($element->nodes, function ($n) { 
      return $n->nodetype == 3;  //Text node type, like in jQuery  
     }); 

     if (!empty($textNode)) { 
      $text = current($textNode); 
      echo $text;   
     } 

    } 

此相呼应:

- dreamer1984 
- monariyadh 

这样做你会。

更新为只能找到每个tr的第一个td。

+0

好的,但是如何避免像数字那样的最后两件事情,如“0,200和0,108”......以及如果我想在不同的地方回显姓名(dreamer1984)和日期...? – harishk

+0

@harishk更新。现在它查找每行的行和第一个“td.Footnotes2”。如果你还想要第三个元素,那么也执行'find(...,2)'。 – apokryfos

+0

Dude,它打印确切的,但重复发出两个错误,如'警告:array_filter()期望参数1是数组,null给出'和'注意:尝试获取非对象的属性'$ textNode = array_filter ($ element-> nodes,function($ n){'line ... – harishk

0

如果你想提取纯文本(不是标签及其包含)

foreach ($html->find("td.FootNotes2") as $element) { 

    $children = $element->children; // get an array of children 
    foreach ($children AS $child) { 
     $child->outertext = ''; // This removes the element, but MAY NOT remove it from the original $myDiv 
    } 
    echo $element->innertext."<br>"; 
} 

O/P:

- dreamer1984 
02/28/17 01:42 
0 
200 
- monariyadh 
02/27/17 23:12 
0 
108 
+0

是的,其实,但我只需要前两列,,,, – harishk

+0

事实上,其他人回答给我的解决方案,但除了当我使用一个while循环时,它给错误...请过来讨论室检查出来... http://chat.stackoverflow.com/rooms/136942/discussion-between-harishk-and-apokryfos – harishk

+0

你有伙计? – harishk

0

你必须使用正则表达式两种方式,使没有意义过于复杂吧:

foreach($html->find('tr') as $tr) { 
    echo preg_replace('/.* - /', '', $tr->find('td',1)->text()) . "\n"; 
    echo $tr->find('td',3)->text() . "\n"; 
} 

我真的不喜欢apokryfos的方法,这是很多困惑,没有任何好处。