Rubino aiuto espressione regolare utilizzando partita per estrarre pezzi di html doc
-
22-08-2019 - |
Domanda
Ho un documento HTML di questo formato:
<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>wmgussio@erols.com</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>osefo@wam.umd.edu</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>
Così alterna - pezzo di informazioni di contatto e poi un "separatore di contatto". Voglio afferrare le informazioni di contatto quindi il mio primo ostacolo è quello di afferrare i pezzi tra il separatore dei contatti. Ho già capito l'espressione regolare utilizzando Rubular. Si tratta di:
/<tr><td colspan="4"><span class="fullName">((.|\s)*?)<hr class="contactSeparator">/
È possibile controllare su Rubular per verificare che questo isola i pezzi.
Tuttavia il mio grande problema è che io sto avendo problemi con il codice Ruby. Io uso il costruito in funzione di partita e fare stampe, ma non ottengo i risultati che si aspettano. Ecco il codice:
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
Si noti che page.body è solo il corpo del documento HTML afferrato per Mechanize. Il documento HTML è molto più grande, ma ha questo formato. Così, l'uscita inaspettata è qui sotto:
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>wmgussio@erols.com</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: ">"
Ci sono 2 sorprese qui per me:
1) Non ci sono 2 partite che contengono i pezzi di informazioni di contatto, anche se il Rubular Ho verificato che questi pezzi devono essere estratti.
2) Tutto il \ r \ n \ t (avanzamenti di riga, tabulazioni, ecc) vengono visualizzati nelle partite.
Chiunque può vedere il problema qui?
In alternativa, se qualcuno sa di un bene gratuito AOL contatti importatore, che sarebbe grande. Sono stato con blackbook, ma continua a non aver per me su AOL e sto cercando di risolvere il problema. Purtroppo, AOL ha ancora contatti API.
Grazie!
Soluzione 4
Questo è il codice che analizza che HTML. Sentitevi liberi di suggerire qualcosa di meglio:
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 screenname@aol.com
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
Altri suggerimenti
Vedere Potete fornire alcuni esempi del perché è difficile analizzare XML e HTML con una regex? per cui questa è una cattiva idea. Utilizzare un href="http://www.google.com/search?q=ruby+html+parser" rel="nofollow noreferrer"> parser HTML .
Se sei solo l'estrazione di informazioni da XML, potrebbe essere più facile da usare qualcosa di diverso da espressioni regolari. XPath è un buon strumento per l'estrazione di informazioni da XML. Credo che ci siano alcune librerie disponibili per Ruby che supportano XPath, magari provare REXML:
Utilizzare un parser HTML come hpricot vi farà risparmiare un sacco di mal di testa:)
sudo gem install hpricot
E 'in gran parte scritto in C, quindi è veloce pure
Ecco come usarlo: