2009-04-02 2 views
0

Ich habe ein HTML-Dokument dieses Formats:Rubin regulärer Ausdruck Hilfe Spiel mit Stücken von html doc zu extrahieren

<tr><td colspan="4"><span class="fullName">Bill Gussio</span></td></tr> 
    <tr> 
     <td class="sectionHeader">Contact</td> 
     <td class="sectionHeader">Phone</td> 
     <td class="sectionHeader">Home</td> 
     <td class="sectionHeader">Work</td> 
    </tr> 
    <tr valign="top"> 
     <td class="sectionContent"><span>Screen Name:</span> <span>bhjiggy</span><br><span>Email 1:</span> <span>[email protected]</span></td> 
     <td class="sectionContent"><span>Mobile: </span><span>2404173223</span></td> 
     <td class="sectionContent"><span>NY</span><br><span>New York</span><br><span>78642</span></td> 
     <td class="sectionContent"><span>MD</span><br><span>Owings Mills</span><br><span>21093</span></td> 
    </tr> 

    <tr><td colspan="4"><hr class="contactSeparator"></td></tr> 

    <tr><td colspan="4"><span class="fullName">Eddie Osefo</span></td></tr> 
    <tr> 
     <td class="sectionHeader">Contact</td> 
     <td class="sectionHeader">Phone</td> 
     <td class="sectionHeader">Home</td> 
     <td class="sectionHeader">Work</td> 
    </tr> 
    <tr valign="top"> 
     <td class="sectionContent"><span>Screen Name:</span> <span>eddieOS</span><br><span>Email 1:</span> <span>[email protected]</span></td> 
     <td class="sectionContent"></td> 
     <td class="sectionContent"><span></span></td> 
     <td class="sectionContent"><span></span></td> 
    </tr> 

    <tr><td colspan="4"><hr class="contactSeparator"></td></tr> 

So ist es abwechselt - Batzen Kontaktdaten und dann ein „Kontakt Trennzeichen“. Ich möchte die Kontaktinformationen erfassen, also ist mein erstes Hindernis, die Brocken zwischen dem Kontaktseparator zu greifen. Den regulären Ausdruck habe ich bereits mit Rubulam gefunden. Es ist:

Sie können auf Rubular überprüfen, um zu überprüfen, dass dies Chunks isoliert.

Allerdings ist mein großes Problem, dass ich Probleme mit dem Ruby-Code habe. Ich benutze die eingebaute Match-Funktion und mache Drucke, aber bekomme nicht die Ergebnisse, die ich erwarte. Hier ist der Code:

page = agent.get uri.to_s  
chunks = page.body.match(/<tr><td colspan="4"><span class="fullName">((.|\s)*?)<hr class="contactSeparator">/).captures 

chunks.each do |chunk| 
    puts "new chunk: " + chunk.inspect 
end 

Beachten Sie, dass page.body ist nur der Körper des HTML-Dokuments von Mechanize ergriffen. Das HTML-Dokument ist viel größer, hat aber dieses Format. So ist die unerwartete Ausgabe unter:

new chunk: "Bill Gussio</span></td></tr>\r\n\t<tr>\r\n\t\t<td class=\"sectionHeader\">Contact</td>\r\n\t\t<td class=\"sectionHeader\">Phone</td>\r\n\t\t<td class=\"sectionHeader\">Home</td>\r\n\t\t<td class=\"sectionHeader\">Work</td>\r\n\t</tr>\r\n\t<tr valign=\"top\">\r\n\t\t<td class=\"sectionContent\"><span>Screen Name:</span> <span>bhjiggy</span><br><span>Email 1:</span> <span>[email protected]</span></td>\r\n\t\t<td class=\"sectionContent\"><span>Mobile: </span><span>2404173223</span></td>\r\n\t\t<td class=\"sectionContent\"><span>NY</span><br><span>New York</span><br><span>78642</span></td>\r\n\t\t<td class=\"sectionContent\"><span>MD</span><br><span>Owings Mills</span><br><span>21093</span></td>\r\n\t</tr>\r\n\t\r\n\t<tr><td colspan=\"4\">" 
new chunk: ">" 

Es gibt 2 Überraschungen für mich:

1) Es gibt keine 2 Ursachen, die die Stücke von Kontaktinformationen enthalten, obwohl auf Rubular ich vergewissert haben, dass Diese Stücke sollten extrahiert werden.

2) Alle \ r \ n \ t (Zeilenvorschübe, Registerkarten usw.) werden in den Übereinstimmungen angezeigt.

Kann jemand das Problem hier sehen?

Alternativ, wenn jemand von einem guten kostenlosen AOL Kontakte Importeur weiß, wäre das toll. Ich habe Blackbook benutzt, aber es scheitert immer noch an AOL und ich versuche es zu beheben. Leider hat AOL noch keine Kontakt-API.

Vielen Dank!

Antwort

0

Dies ist der Code, der das HTML analysiert.Fühlen Sie sich frei, etwas vorzuschlagen, besser:

contacts = [] 
    email, mobile = "","" 

    names = page.search("//span[@class='fullName']") 

    # Every contact has a fullName node, so for each fullName node, we grab the chunk of contact info 
    names.each do |n| 

     # next_sibling.next_sibling skips: 
     # <tr> 
     # <td class=\"sectionHeader\">Contact</td> 
     # <td class=\"sectionHeader\">Phone</td> 
     # <td class=\"sectionHeader\">Home</td> 
     # <td class=\"sectionHeader\">Work</td> 
     # </tr> 
     # to give us the actual chunk of contact information 
     # then taking the children of that chunk gives us rows of contact info 
     contact_info_rows = n.parent.parent.next_sibling.next_sibling.children 

     # Iterate through the rows of contact info 
     contact_info_rows.each do |row| 

     # Iterate through the contact info in each row 
     row.children.each do |info| 
      # Get Email. There are two ".next_siblings" because space after "Email 1" element is processed as a sibling 
      if info.content.strip == "Email 1:" then email = info.next_sibling.next_sibling.content.strip end 

      # If the contact info has a screen name but no email, use [email protected] 
      if (info.content.strip == "Screen Name:" && email == "") then email = info.next_sibling.next_sibling.content.strip + "@aol.com" end 

      # Get Mobile #'s 
      if info.content.strip == "Mobile:" then mobile = info.next_sibling.content.strip end 

      # Maybe we can try and get zips later. Right now the zip field can look like the street address field 
      # so we can not tell the difference. There is no label node 
      #zip_match = /\A\D*(\d{5})-?\d{4}\D*\z/i.match(info.content.strip) 
      #zip_match = /\A\D*(\d{5})[^\d-]*\z/i.match(info.content.strip)  
     end 

     end 

     contacts << { :name => n.content, :email => email, :mobile => mobile } 

     # clear variables 
     email, mobile = "", "" 
    end 
3

Wenn Sie nur Informationen aus XML extrahieren, ist es möglicherweise einfacher, etwas anderes als reguläre Ausdrücke zu verwenden. XPath ist ein gutes Werkzeug zum Extrahieren von Informationen aus XML. Ich glaube, es gibt einige Bibliotheken für Ruby verfügbar sind, die XPath unterstützen, vielleicht REXML versuchen:

+0

Insbesondere extrahiere ich aus HTML. Ich habe mit XPATH herumgespielt, aber aufgrund der genauen Daten, die ich herausholen möchte, scheint es wirklich sehr schwierig zu sein, das zu bekommen, was ich will. Es scheint, dass XPATH gut ist, um alle Daten zwischen 2 Knoten zu bekommen, das ist nicht was ich will. Auch XPATH-Dokumente für Ruby sind schlecht! – Tony

3

Verwenden Sie einen HTML-Parser wie hpricot Sie viele Kopfschmerzen sparen :)

sudo gem hpricot installieren

Es meist in C geschrieben So ist es auch schnell

Hier ist, wie es zu verwenden:

http://wiki.github.com/why/hpricot/hpricot-basics

+0

endete mit nokogiri – Tony

+0

Yup, es gibt Nokogiri auch ... Es ist ein neuer Anwärter des Parserbereichs –

Verwandte Themen