2010-07-16 8 views
3

Je suis en train d'utiliser nokogiri pour analyser le segment suivantNokogiri: Parsing irrégulière "<"

<tr> 
<th>Total Weight</th> 
<td>< 1 g</td> 
<td style="text-align: right">0 %</td> 

</tr>    
<tr><td class="skinny_black_bar" colspan="3"></td></tr> 

Cependant, je pense que le "<" signe dans "< 1 g" est à l'origine des problèmes Nokogiri. Est-ce que quelqu'un sait des solutions de contournement? Est-il possible que je puisse échapper au signe "<"? Ou peut-être y at-il une fonction que je peux appeler pour obtenir le segment html?

Répondre

2

Le "inférieur à" (<) isn't legal HTML, mais les navigateurs ont beaucoup de code pour comprendre ce que l'on entend par le HTML au lieu de simplement afficher une erreur. C'est pourquoi votre exemple HTML incorrect affiche la façon dont vous le souhaitez dans les navigateurs. Donc, l'astuce consiste à s'assurer que Nokogiri fait le même travail pour compenser le mauvais code HTML. Assurez-vous d'analyser le fichier HTML au lieu de XML:

f = File.open("table.html") 
doc = Nokogiri::HTML(f) 

Ce fichier parse très bien, mais jette le texte < 1 g. Regardez comment le contenu des 2 premiers éléments de TD est analysé:

doc.xpath('(//td)[1]/text()').to_s 
=> "\n " 

doc.xpath('(//td)[2]/text()').to_s 
=> "0 %" 

Nokogiri a jeté votre texte invalide, mais a gardé l'analyse de la structure environnante. Vous pouvez même le message d'erreur de Nokogiri:

doc.errors 
=> [#<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>] 
doc.errors[0].line 
=> 3 

Eh oui, la ligne 3 est mauvais. Il semble donc que Nokogiri n'a pas le même niveau de support pour l'analyse syntaxique de HTML invalide que les navigateurs. Je recommande d'utiliser une autre bibliothèque pour prétraiter vos fichiers. J'ai essayé de courir TagSoup sur votre fichier d'exemple et elle a fixé le < en changeant à &lt; comme ceci:

% java -jar tagsoup-1.1.3.jar foo.html | xmllint --format - 
src: foo.html 
<?xml version="1.0" standalone="yes"?> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <body> 
    <table> 
     <tbody> 
     <tr> 
      <th colspan="1" rowspan="1">Total Weight</th> 
      <td colspan="1" rowspan="1">&lt;1 g</td> 
      <td colspan="1" rowspan="1" style="text-align: right">0 %</td> 
     </tr> 
     <tr> 
      <td colspan="3" rowspan="1" class="skinny_black_bar"/> 
     </tr> 
     </tbody> 
    </table> 
    </body> 
</html> 
+0

Y a-t-il des paquets Ruby qui analysent HTML aussi fermement que TagSoup? – sampablokuper

4

Comme une solution rapide, je suis venu avec cette méthode en utilisant une expression reqular pour identifier les balises non fermées:

def fix_irregular_html(html) 
    regexp = /<([^<>]*)(<|$)/ 

    #we need to do this multiple time as regex are overlapping 
    while (fixed_html = html.gsub(regexp, "&lt;\\1\\2")) && fixed_html != html 
    html = fixed_html 
    end 

    fixed_html 
end 

Voir code complet y compris le test ici: https://gist.github.com/796571

Il fonctionne bien pour moi, je vous remercie des commentaires et des améliorations