2011-05-13 14 views
5

Próbuję wydobyć nazwę, ID, telefon, e-mail, płeć, pochodzenie etniczne, DOB, klasę, majora, szkołę i GPA ze strony, którą parsuję z Nokogiri.Jak używać Nokogiri i Ruby do skrobania wartości z HTML za pomocą zagnieżdżonych tabel?

Próbowałem kilka różnych XPath, ale wszystko staram chwyta znacznie więcej niż chcę:

<span class="subTitle"><b>Recruit Profile</b></span> 
<br><table border="0" width="100%"><tr> 
<td> 
     <table bgcolor="#afafaf" border="0" cellpadding="0" width="100%"> 
<tr> 
<td> 
     <table bgcolor="#cccccc" border="0" cellpadding="2" cellspacing="2" width="100%"> 
<tr> 
<td bgcolor="#dddddd"><b>Name</b></td> 
      <td bgcolor="#dddddd">Some Person</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>EDU ID</b></td> 
      <td bgcolor="#dddddd">A12345678</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Phone</b></td> 
      <td bgcolor="#dddddd">123-456-7890</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Address</b></td> 
      <td bgcolor="#dddddd">1234 Somewhere Dr.<br>City ST, 12345</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Email</b></td> 
      <td bgcolor="#dddddd">[email protected]</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Gender</b></td> 
      <td bgcolor="#dddddd">Female</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Ethnicity</b></td> 
      <td bgcolor="#dddddd">Unknown</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Date of Birth</b></td> 
      <td bgcolor="#dddddd">Jan 1st, 1901</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Class</b></td> 
      <td bgcolor="#dddddd">Sophomore</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>Major</b></td> 
      <td bgcolor="#dddddd">Biology</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>School</b></td> 
      <td bgcolor="#dddddd">University of Somewhere</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd"><b>GPA</b></td> 
      <td bgcolor="#dddddd">0.00</td> 
     </tr> 
<tr> 
<td bgcolor="#dddddd" valign="top"><b>Availability</b></td> 
      <td bgcolor="#dddddd"> 
     <table border="0" cellspacing="0" cellpadding="0"> 
<tr> 
+0

+! Doskonała praca, w tym próbka rzeczywistego kodu HTML, który musisz przeanalizować. – Phrogz

Odpowiedz

5

Zakładam, że będzie wiele „Rekrut Profil” przęseł, które są stosowane przez tabel zakończyć wszystkie szczegóły . Poniższa metoda zajmuje całą stronę HTML, znajdzie tylko te zakresy, a dla każdego z nich znajdzie się w poniższej tabeli, a następnie wyszukuje pola chcesz nigdzie poniżej tej tabeli:

require 'nokogiri' 

# Pass in or set the array of labels you want to use 
# Returns an array of hashes mapping these labels to the values 
def recruits_details(html,fields=%W[Name #{"EDU ID"} Phone Email Gender]) 
    doc = Nokogiri::HTML(html) 
    recruit_labels = doc.xpath('//span[b[text()="Recruit Profile"]]') 
    recruit_labels.map do |recruit_label| 
    recruit_table = recruit_label.at_xpath('following-sibling::table') 
    Hash[ fields.map do |field_label| 
     label_td = recruit_table.at_xpath(".//td[b[text()='#{field_label}']]") 
     [field_label, label_td.at_xpath('following-sibling::td/text()').text ] 
    end ] 
    end 
end 

require 'pp' 
pp recruits_details(html_string) 
#=> [{"Name"=>"Some Person", 
#=> "EDU ID"=>"A12345678", 
#=> "Phone"=>"123-456-7890", 
#=> "Email"=>"[email protected]", 
#=> "Gender"=>"Female"}] 

Wyrażenie XPath jak .//foo[bar[text()="jim"]] oznacza:

  • Znajdź 'foo' elementu w dowolnym miejscu w ramach obecnego węzła
  • ... ale tylko wtedy, gdy ma ona 'bar' element jako dziecko
  • ... ale tylko wtedy, gdy „bar” element ma tekst „Jim”, jak jego treści
wyrażenie

XPath jak following-sibling::... oznacza znaleźliśmy żadnych elementów, które są rodzeństwem, począwszy od bieżącego węzła, który pasuje do wyrażenie ...

Wyrażenie XPath .../text() wybiera Text node; Metoda text służy do wyodrębnienia wartości (rzeczywistego ciągu znaków) tego węzła tekstowego.

Metoda Nokogiriego xpath zwraca tablicę wszystkich elementów pasujących do wyrażenia, natomiast metoda at_xpath zwraca pierwszy element pasujący do wyrażenia.

+0

Dzięki za szybką reakcję! Niedługo to sprawdzę! – Sean

+0

Bardzo dziękuję, po kilku hackach udało mi się to doskonale! Dzięki! – Sean

+0

Wiesz, jeśli miałbyś fanklub, zostałbym prezydentem. – Sean