2011-05-13 6 views
5

Sto cercando di estrarre il nome, l'ID, il telefono, l'email, il genere, l'etnia, il DOB, la classe, il maggiore, la scuola e il GPA da una pagina che sto analizzando con Nokogiri.Come utilizzare Nokogiri e Ruby per acquisire i valori dall'HTML con le tabelle nidificate?

Ho provato alcuni differenti XPath di ma tutto provo palio molto di più di quanto io voglio:

<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

+! Lavoro eccellente che include un esempio dell'HTML effettivo da analizzare. – Phrogz

risposta

5

presumo che ci saranno molti "Recluta profilo" campate che sono seguiti da tabelle che avvolgono tutti i dettagli . Il metodo seguente prende l'intera pagina HTML, trova solo quelle campate, e per ciascuno di essi si trova la seguente tabella e poi trova i campi desiderati ovunque sotto quel tavolo:

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"}] 

un'espressione XPath come .//foo[bar[text()="jim"]] significa:

  • Trova un elemento 'pippo' ovunque sotto il nodo corrente
  • ... ma solo se ha un elemento di 'bar' come un bambino
  • ... ma solo se quell'elemento 'bar' è il testo "jim", come il suo contenuto

un XPath espressione come following-sibling::... significa Trova tutti gli elementi che sono fratelli e sorelle, dopo il nodo corrente che corrispondono al espressione ...

L'espressione XPath .../text() seleziona Text node; il metodo text viene utilizzato per estrarre il valore (stringa effettiva) di quel nodo di testo.

Il metodo xpath di Nokogiri restituisce un array di tutti gli elementi che corrispondono all'espressione, mentre il metodo at_xpath restituisce il primo elemento che corrisponde all'espressione.

+0

Grazie per la rapida risposta! Prenderò a testare questo a breve! – Sean

+0

Grazie mille, dopo un po 'di hacking ho capito che funziona perfettamente! Grazie! – Sean

+0

Solo per quello che sai, se tu avessi un fan club, sarei il presidente. – Sean