【问题标题】:Can't separate cells properly with simplehtmldom无法使用 simplehtmldom 正确分隔单元格
【发布时间】:2009-07-26 01:10:37
【问题描述】:

我正在尝试编写一个网络爬虫。我想连续获取所有单元格。我想要的行之前的行有 THOROUGHBRED MEETINGS 作为其纯文本值。我可以成功得到这一行。但我不知道如何获取下一行的子单元格或<td> 标签。

if ($foundTag = FindTagByText("THOROUGHBRED MEETINGS", $html))
{
    $cell = $foundTag->parent();
    $row = $cell->parent();
    $nextRow = $row->next_sibling();
    echo "Row: ".$row->plaintext."<br />\n";
    echo "Next Row: ".$nextRow->plaintext."<br />\n";
    $cells = $nextRow->children();

    foreach ($cells as $cell)
    {
        echo "Cell: ".$cell->plaintext."<br />\n";
    }
}

function FindTagByText($text, $html)
{
    // Use Simple_HTML_DOM special selector 'text'
    // to retrieve all text nodes from the document
    $textNodes = $html->find('text');
    $foundTag = null;

    foreach($textNodes as $textNode) 
    {
        if($textNode->plaintext == $text) 
        {
            // Get the parent of the text node
            // (A text node is always a child of
            //  its container)
            $foundTag = $textNode->parent();
            break;
        }
    }

    return $foundTag;
}

这是我要解析的 html:

<tr valign=top>
<td colspan=16 bgcolor=#999999><b>THOROUGHBRED MEETINGS</b></td>

</tr>
<tr valign=top bgcolor="#ffffff">
<td><b>BR</b> <a href="meeting?mtg=br&day=today&curtype=0">SUNSHINE COAST</a></td>
<td>FINE/DEAD</b></td>
<td><font color=#cc0000><b>R1</b></font>@<b>12:30pm</b></td>
<td align=center bgcolor=#cc0000><a href="odds?mting=BR01000"><b><font color=#ffffff>1</a></font></td>
<td align=center><a href="odds?mting=BR02000"><b><font color=black>2</b></font></a></td>
<td align=center><a href="odds?mting=BR03000"><b><font color=black>3</b></font></a></td>

<td align=center><a href="odds?mting=BR04000"><b><font color=black>4</b></font></a></td>
<td align=center><a href="odds?mting=BR05000"><b><font color=black>5</b></font></a></td>
<td align=center><a href="odds?mting=BR06000"><b><font color=black>6</b></font></a></td>
<td align=center><a href="odds?mting=BR07000"><b><font color=black>7</b></font></a></td>
<td align=center><a href="odds?mting=BR08000"><b><font color=black>8</b></font></a></td>
<td bgcolor="#ffffff" colspan=4>&nbsp;</td>
</tr>

这是我的输出:

行:彻底的会议 下一行:BR SUNSHINE COAST FINE/DEAD R1@12:30pm 1 2 3 4 5 6 7 8 CR NEW ZEALAND FINE/DEAD R3@11:10am 1 2 3 4 5 6 7 8 9 DR HOBART OCAST/HVY R1@12 :15pm 1 2 3 4 5 6 7 MR CRANBOURNE OCAST/SLOW R1@12:20pm 1 2 3 4 5 6 7 8 NR COFFS HARBOR OCAST/SLOW R1@12:45pm 1 2 3 4 5 6 7 8 SR MORUYA FINE/良好 R1@12:25pm 1 2 3 4 5 6 7 8 VR BENALLA OCAST/SLOW R1@12:35pm 1 2 3 4 5 6 7 8 XR KALGOORLIE FINE/GOOD R1@ 3:00pm 1 2 3 4 5 6 7 线束会议 DT 朗塞斯顿 SHWRY/GOOD R1@ 下午 4:57 1 2 3 4 5 6 7 8 9 10 MT CRANBOURNE OCAST/GOOD R1@ 下午 5:05 1 2 3 4 5 6 7 8 GREYHOUND 会议 AD GAWLER OCAST/GOOD R1@ 5: 10pm 1 2 3 4 5 6 7 8 9 10 11 CD CANBERRA OCAST/GOOD R1@ 5:02pm 1 2 3 4 5 6 7 8 9 10 11 MD SALE FINE/GOOD R1@ 4:54pm 1 2 3 4 5 6 7 8 9 10 11 12 单元格:BR 阳光海岸 细胞:好/死 单元格:R1@12:30pm 单元:1 2 3 4 5 6 7 8 CR NEW ZEALAND FINE/DEAD R3@11:10am 1 2 3 4 5 6 7 8 9 DR HOBART OCAST/HVY R1@12:15pm 1 2 3 4 5 6 7 MR CRANBOURNE OCAST /SLOW R1@12:20pm 1 2 3 4 5 6 7 8 NR COFFS HARBOR OCAST/SLOW R1@12:45pm 1 2 3 4 5 6 7 8 SR MORUYA FINE/GOOD R1@12:25pm 1 2 3 4 5 6 7 8 VR BENALLA OCAST/SLOW R1@12:35pm 1 2 3 4 5 6 7 8 XR KALGOORLIE FINE/GOOD R1@ 3:00pm 1 2 3 4 5 6 7 线束会议 DT 朗塞斯顿 SHWRY/GOOD R1@ 4:57pm 1 2 3 4 5 6 7 8 9 10 MT CRANBOURNE OCAST/GOOD R1@ 5:05pm 1 2 3 4 5 6 7 8 GREYHOUND MEETINGS AD GAWLER OCAST/GOOD R1@ 5:10pm 1 2 3 4 5 6 7 8 9 10 11 CD CANBERRA OCAST/GOOD R1@ 5:02pm 1 2 3 4 5 6 7 8 9 10 11 MD SALE FINE/GOOD R1@ 4:54pm 1 2 3 4 5 6 7 8 9 10 11 12

【问题讨论】:

  • 您希望输出是什么样的?我很困惑,因为看起来你的输出正是你想要的,不是吗?
  • 输出应为: 单元格:BR SUNSHINE COAST FINE/DEAD R1@12:30pm 1 2 3 4 5 6 7 8 单元格:CR NEW ZEALAND FINE/DEAD R3@11:10am 1 2 3 4 5 6 7 8 9 单元:霍巴特博士 OCAST/HVY R1@12:15pm 1 2 3 4 5 6 7 等

标签: php screen-scraping simple-html-dom


【解决方案1】:

你不会喜欢我的回答。

不幸的是,您正在解析的 HTML 中不匹配的结束标记似乎使 Simple_HTML_DOM 感到困惑。看看这个sn-p:

<td align=center><a href="odds?mting=BR02000"><b><font color=black>2</b></font></a></td>

如果按照这个sn-p的标签顺序:

  • &lt;td&gt;已开通
  • &lt;a&gt;已开通
  • &lt;b&gt;已开通
  • &lt;font&gt;已开通

从技术上讲,标签应该以相反的顺序关闭,但它们是这样关闭的:

  • &lt;/b&gt; 已关闭
  • &lt;/font&gt; 已关闭
  • &lt;/a&gt; 已关闭
  • &lt;/td&gt;已关闭

您尝试抓取的 HTML 充满了这些错误,以及从未打开的标签的结束标签。 Simple_HTML_DOM 没有正确解析这些文件。

恐怕如果您无法修改 HTML,您将不得不手动解析文件,纠正任何错误。


请注意,我已经针对以下更正的 HTML 测试了您的代码,Simple_HTML_DOM 成功解析了它,并且您的代码运行良好。

<tr valign=top>
<td colspan=16 bgcolor=#999999><b>THOROUGHBRED MEETINGS</b></td>

</tr>
<tr valign=top bgcolor="#ffffff">
<td><b>BR</b> <a href="meeting?mtg=br&day=today&curtype=0">SUNSHINE COAST</a></td>
<td><b>FINE/DEAD</b></td>
<td><font color=#cc0000><b>R1</font></b>@<b>12:30pm</b></td>
<td align=center bgcolor=#cc0000><a href="odds?mting=BR01000"><b><font color=#ffffff>1</a></b></font></td>
<td align=center><a href="odds?mting=BR02000"><b><font color=black>2</font></b></a></td>
<td align=center><a href="odds?mting=BR03000"><b><font color=black>3</font></b></a></td>

<td align=center><a href="odds?mting=BR04000"><b><font color=black>4</font></b></a></td>
<td align=center><a href="odds?mting=BR05000"><b><font color=black>5</font></b></a></td>
<td align=center><a href="odds?mting=BR06000"><b><font color=black>6</font></b></a></td>
<td align=center><a href="odds?mting=BR07000"><b><font color=black>7</font></b></a></td>
<td align=center><a href="odds?mting=BR08000"><b><font color=black>8</font></b></a></td>
<td bgcolor="#ffffff" colspan=4> </td>
</tr>

编辑: 如果DOMDocument::loadHTML 有更好的结果,您可能想尝试一下。它在没有外部库的 PHP 5 中可用。检查the official documentation

【讨论】:

  • 正确的 HTML 解析是一个相当复杂的主题。恐怕我帮不了你。
  • 1+ 用于发现无效的 html。我没有注意到这一点。 Glen,我认为您应该接受无法正确解析无效语法的事实。或者如果你真的需要解析这个页面,只需硬编码一些东西。如果您首先删除所有 标记,您应该能够解析其余部分。
  • @Wouter van Nifterick: 应该...我们不知道页面的其余部分以及它如何影响解析。但是对于这个sn-p来说,是一个可行的方案。
【解决方案2】:

你会得到这样的第一个 td:

$firstTD = $row->first_child();

之后你可以得到后续的:

$firstTD->next_sibling()

【讨论】:

  • 致命错误:在第 37 行的 /var/www/php.php 中调用未定义的方法 simple_html_dom_node::child_nodes()
  • 致命错误:在第 37 行的 /var/www/php.php 中调用未定义的方法 simple_html_dom_node::domnode_next_sibling()
  • 对不起.. 这是$firstTD-&gt;next_sibling();
  • 我仍然遇到与该代码相同的问题。它只是将所有兄弟姐妹混入一个领域。它没有分隔 &lt;td&gt; 标签
【解决方案3】:

我通过将其放入 DOMDocument() 来纠正格式错误的 HTML。

$url = "http://www.acttab.com.au/interbet/venues?day=today";

$doc = new DOMDocument();
$doc->loadHTMLFile($url);

//convert $doc to html
$html = str_get_html($doc->saveHTML());

【讨论】:

    猜你喜欢
    • 2013-08-14
    • 2019-01-19
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    相关资源
    最近更新 更多