用于解析HTML电子邮件的正则表达式无法捕获多个元素

时间:2013-11-12 18:05:51

标签: html ruby regex

我正在尝试解析PayPal HTML电子邮件以获取不同的项目。例如,有一个显示所有购买物品的价格,单位和总数。

这是我试图解析的<table>

<table align="center" border="0" cellpadding="0" cellspacing="0" style="clear:both;color:#333!important;font-size:12px;font-family:arial,helvetica,sans-serif" width="598px">
   <tbody>
      <tr>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="348" align="left">Description</td>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="100" align="right">Unit price</td>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="50" align="right">Qty</td>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="80" align="right">Amount</td>
      </tr>
      <tr>
         <td valign="top" align="left" style="border-bottom:none;padding:10px"><a href="http://cgi.ebay.es/ws/eBayISAPI.dll?ViewItem&amp;item=171154674852" target="_blank">FUNDA PIEL FUCSIA PARA BQ AQUARIUS 4.5. GRAN CALIDAD.</a><br>Item# 171154674852</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€3,50 EUR</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">1</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€3,50 EUR</td>
      </tr>
      <tr>
         <td valign="top" align="left" style="border-bottom:none;padding:10px"><a href="http://cgi.ebay.es/ws/eBayISAPI.dll?ViewItem&amp;item=171154674852" target="_blank">FUNDA PIEL ROJA PARA IPHONE 4.5. GRAN CALIDAD.</a><br>Item# 171154674852</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€10,50 EUR</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">1</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€10,50 EUR</td>
      </tr>
   </tbody>
</table>

我使用match来检测并捕获不同的变量(Ruby):

unless /thePreviousRegexp/.match(body).nil?
    item = /thePreviousRegexp/.match(body)[:item]
    price_unit = /thePreviousRegexp/.match(body)[:price_unit]
end

好吧,当我只有一个项目时它会起作用。但是,当我有一个以上时,它只需要最后一个。我想抓住所有这些。

我怎么能这样做?我把&lt; tr>属于()+中的表,这意味着模式可以重复一次或多次。但它似乎没有用。

2 个答案:

答案 0 :(得分:2)

使用Nokogiri

我会这样做:

require 'nokogiri'

doc = Nokogiri::HTML.parse <<-eot
<table align="center" border="0" cellpadding="0" cellspacing="0" style="clear:both;color:#333!important;font-size:12px;font-family:arial,helvetica,sans-serif" width="598px">
   <tbody>
      <tr>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="348" align="left">Description</td>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="100" align="right">Unit price</td>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="50" align="right">Qty</td>
         <td style="border:1px solid #ccc;border-right:none;border-left:none;padding:5px 10px 5px 10px!important;color:#333333" width="80" align="right">Amount</td>
      </tr>
      <tr>
         <td valign="top" align="left" style="border-bottom:none;padding:10px"><a href="http://cgi.ebay.es/ws/eBayISAPI.dll?ViewItem&amp;item=171154674852" target="_blank">FUNDA PIEL FUCSIA PARA BQ AQUARIUS 4.5. GRAN CALIDAD.</a><br>Item# 171154674852</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€3,50 EUR</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">1</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€3,50 EUR</td>
      </tr>
      <tr>
         <td valign="top" align="left" style="border-bottom:none;padding:10px"><a href="http://cgi.ebay.es/ws/eBayISAPI.dll?ViewItem&amp;item=171154674852" target="_blank">FUNDA PIEL ROJA PARA IPHONE 4.5. GRAN CALIDAD.</a><br>Item# 171154674852</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€10,50 EUR</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">1</td>
         <td valign="top" align="right" style="border-bottom:none;padding:10px">€10,50 EUR</td>
      </tr>
   </tbody>
</table>
eot

table_header = doc.xpath("//table//tr[1]/td").map(&:text)
# => ["Description", "Unit price", "Qty", "Amount"]

product_information = doc.xpath("//table//tr[position()!=1]").map do |e|
  Hash[table_header.zip(e.css('td').map(&:text))]
end

product_information
# => [{"Description"=>
#       "FUNDA PIEL FUCSIA PARA BQ AQUARIUS 4.5. GRAN CALIDAD.Item# 171154674852",
#      "Unit price"=>"€3,50 EUR",
#      "Qty"=>"1",
#      "Amount"=>"€3,50 EUR"},
#     {"Description"=>
#       "FUNDA PIEL ROJA PARA IPHONE 4.5. GRAN CALIDAD.Item# 171154674852",
#      "Unit price"=>"€10,50 EUR",
#      "Qty"=>"1",
#      "Amount"=>"€10,50 EUR"}]

答案 1 :(得分:1)

而不是使用match您需要使用exec方法并使用while循环重复此方法。
只使用这样的短正则表达式:

/item=(\d*?)\".*?€([\d\,]+) EUR/g

希望它有所帮助,但不是在犯罪活动中。