【问题标题】:Nokogiri parse HTML table in RubyNokogiri parse HTML table in Ruby
【发布时间】:2012-09-21 01:39:57
【问题描述】:

我需要使用 Nokogiri 从 URL 解析 HTML 表。我的 HTML 如下所示:

<table class="tbl" cellspacing="1" cellpadding="4" id="gvResult" style="width:100%;">
   <tbody>
      <tr class="trh">
         <th scope="col"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$1')">Фирма</a></th>
         <th scope="col"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$2')">Артикул</a></th>
         <th scope="col">Инф.</th>
         <th scope="col"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$3')">Описание</a></th>
         <th scope="col"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$6')">Нал.</a></th>
         <th scope="col" style="width:55px;"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$8')">Мин. заказ, шт</a></th>
         <th scope="col"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$5')">Ожидаемый срок, дн. </a><a href="/help/hint/default.aspx?id=43" onclick="javascript:ShowTipLayer(this, event,this.href,30,20);return false;"><img src="http://s.exist.ru/img/q2.gif" alt="&#1055;&#1086;&#1084;&#1086;&#1097;&#1100;" /></a></th>
         <th scope="col"><a href="javascript:__doPostBack('ctl00$ctl00$b$b$gvResult','Sort$7')">Цена</a></th>
         <th scope="col">&nbsp;</th>
      </tr>
      <tr>
         <td class="tabletitle" colspan="12">Запрошенный артикул</td>
      </tr>
      <tr onclick="colorize(this);" id="item_0" tcolor="">
         <td class="artMerge" id="item_0" rowspan="2"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=47721138-000d-40c7-99f1-02d2f0005c83">Knecht (Mahle Filter)</a></td>
         <td class="artMerge" rowspan="2" style="white-space:nowrap;">O * * * D</td>
         <td class="artMerge" align="center" rowspan="2" style="white-space:nowrap;"></td>
         <td class="artMerge" rowspan="2" style="padding:10px 10px 0 10px;">Фильтр масляный</td>
         <td align="center">99</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-38be-0297-2f1100002de2" target="_blank">0</a></td>
         <td class="price" align="right">56&nbsp;400 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-38be-0297-2f1100002de2&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_1" tcolor="">
         <td align="center">1782</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=1&amp;s=0100f98e-5c00-b5be-0297-0f1200002de2" target="_blank">1</a></td>
         <td class="price" align="right">55&nbsp;000 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-b5be-0297-0f1200002de2&amp;sr=-4"></a></td>
      </tr>
      <tr>
         <td class="tabletitle" colspan="12">Аналоги (заменители) для запрошенного артикула <a href="/news/newstext.aspx?id=1367" target="_blank"><img src="http://s.exist.ru/img/q2.gif" alt="&#1055;&#1086;&#1084;&#1086;&#1097;&#1100;" /></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_2" tcolor="">
         <td class="firmname" id="item_2"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=e0c712d8-215d-4000-9a64-f02c7200005c">Alco</a></td>
         <td style="white-space:nowrap;">M * * * 5</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">1</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-71fb-0241-720c00002c7d" target="_blank">0</a></td>
         <td class="price" align="right">37&nbsp;700 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-71fb-0241-720c00002c7d&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_3" tcolor="">
         <td class="firmname" id="item_3"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=b113459e-001c-4000-a33e-5021bd20005c">Bosch</a></td>
         <td style="white-space:nowrap;">1 * * * 9</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">8</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-3495-0002-bd11000021c2" target="_blank">0</a></td>
         <td class="price" align="right">30&nbsp;200 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-3495-0002-bd11000021c2&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_4" tcolor="">
         <td class="firmname" id="item_4"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=40f20c71-000a-400f-bd7d-02c720005c78">Champion</a></td>
         <td style="white-space:nowrap;">X * * * 6</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">1</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-713d-0142-720c00002cb0" target="_blank">0</a></td>
         <td class="price" align="right">59&nbsp;500 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-713d-0142-720c00002cb0&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_5" tcolor="">
         <td class="firmname" id="item_5"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=50d11138-0008-4436-b40f-02d2f0005cc4">Clean filters</a></td>
         <td style="white-space:nowrap;">M * * * 0</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">100</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-385f-012b-2f1100002df5" target="_blank">0</a></td>
         <td class="price" align="right">32&nbsp;500 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-385f-012b-2f1100002df5&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_6" tcolor="">
         <td class="firmname" id="item_6"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=e0cb777d-0ecd-4000-8f30-802be890005c">Filtron</a></td>
         <td style="white-space:nowrap;">O * * * 1</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">10</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-b781-0297-e80c00002be2" target="_blank">0</a></td>
         <td class="price" align="right">29&nbsp;000 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-b781-0297-e80c00002be2&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_7" tcolor="">
         <td class="firmname" id="item_7"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=64e20c71-000c-40c6-8e51-02c720005c0f">Fram</a></td>
         <td style="white-space:nowrap;">C * * * O</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">31</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-7151-00e8-720c00002c21" target="_blank">0</a></td>
         <td class="price" align="right">45&nbsp;500 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-7151-00e8-720c00002c21&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_8" tcolor="">
         <td class="firmname" id="item_8"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" href="hint/?s=a1135e09-11ba-4000-a216-d02b3670005c">Hengst</a></td>
         <td style="white-space:nowrap;">E * * * 8</td>
         <td align="center" style="white-space:nowrap;"></td>
         <td>Фильтр масляный</td>
         <td align="center">10</td>
         <td align="center">1</td>
         <td class="statis"><a class="stat" onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false" href="/stat/hint/deliv.aspx?d=0&amp;s=0100f98e-5c00-35e4-0024-361100002b92" target="_blank">0</a></td>
         <td class="price" align="right">48&nbsp;900 р.</td>
         <td class="basket"><a title="&#1050;&#1091;&#1087;&#1080;&#1090;&#1100;" href="/profile/orders/basket.aspx?pid=83A07C7A&amp;in=0100f98e-5c00-35e4-0024-361100002b92&amp;sr=-4"></a></td>
      </tr>
      <tr onclick="colorize(this);" id="item_9" tcolor="">
         <td class="firmname" id="item_9"><a onclick="javascript:ShowTipLayer(this,event,this.href, 30,130); return false;" 
        ...
      </tr>
   </tbody>
</table>

还要注意它有俄罗斯符号。

我的 Ruby 代码如下所示:

html = open('http://exist.by/price.aspx?pcode=ox143d')
    require 'nokogiri'
    require 'pp'
    doc = Nokogiri::HTML(html)
    doc.encoding = 'utf-8'

    rows = doc.xpath('//table[@id="gvResultTable"]/tbody/tr[@id="item_1"]')
    @details = rows.collect do |row|
      detail = {}
      [
        [:firmname, 'td[1]/text()'],
        [:price, 'td[8]/text()'],
      ].each do |name, xpath|
        detail[name] = row.at_xpath(xpath).to_s.strip
      end
      detail
    end
    pp @details
    logger.warn("!!!!!!!!!!")
    logger.warn(@details)

我不知道如何使用itemid 正确获取tr 中的数据。

【问题讨论】:

  • 您能否更具体地说明您遇到问题的地方以及您的问题是什么?
  • @MarkThomas 我需要从表中获取数据(您可以从代码中查看 url)并从那里获取品牌价值和我的应用程序的价格。上面是表鳕鱼的一部分。

标签: ruby-on-rails ruby html-parsing nokogiri


【解决方案1】:
  1. HTML 存在缺陷;有多个元素具有相同的id 属性:&lt;tr onclick="colorize(this);" id="item_2" tcolor=""&gt; &lt;td class="firmname" id="item_2"&gt;
  2. HTML 中 table 元素的 id 是“gvResult”,而在 Ruby 代码中,您要求 Nokogiri 查找包含“id=gvResultTable”的表。
  3. Nokogiri 使用 UTF-8 编码在内部存储字符串,因此您应该对俄语字符没有任何问题。

如果可以修复 HTML,则可以正常工作:

HTML:

<table id="gvResult">
  <tbody>
    <tr id="item_1">
        <td class="firmname">Example1</td>
        <td class="price">42.00</td>
    </tr>
    <tr id="item_2">
       <td class="firmname">Example2</td>
       <td class="price">24.00</td>
    </tr>
  </tbody>
</table>

鲁比:

require 'rubygems'
require 'nokogiri'
require 'pp'

html = open('http://www.example.com/page')

doc = Nokogiri::HTML(html)
doc.encoding = 'utf-8'

rows = doc.search('//tr[starts-with(@id, "item_")]')
  @details = rows.collect do |row|
      detail = {}
      [
        [:firmname, 'td[1]/text()'],
        [:price, 'td[2]/text()'],
      ].each do |name, xpath|
        detail[name] = row.at_xpath(xpath).to_s.strip
      end
      detail
  end
pp @details

我假设您想从所有带有idtr 元素中获取数据,例如“item_\d+”,因此我使用了doc.search('//tr[starts-with(@id, "item_")]')。更改它以满足您的需要。

【讨论】:

  • 我无法更改 html...这不是我的页面
  • 我确实提到了“如果 HTML 可以修复.....” :-) 代码仍然可以工作,试一试。
猜你喜欢
  • 2010-12-17
  • 2016-09-25
  • 2011-01-29
  • 1970-01-01
  • 2012-12-15
  • 2021-02-10
  • 1970-01-01
  • 2014-05-28
  • 2013-05-02
相关资源
最近更新 更多