Démarrer avec Nokogiri

Installation ou configuration

Instructions détaillées sur la configuration ou l’installation de Nokogiri.

Comment analyser HTML ou XML dans un document Nokogiri XML ou HTML

Il n’y a pas grand-chose à ajouter au didacticiel “[Parsing an HTML/XML Document][1]” de Nokogiri, qui est une introduction facile au sujet, alors commencez par là, puis revenez à cette page pour aider à combler certaines lacunes.

L’analyse de base de Nokogiri tente de nettoyer un document mal formé, en ajoutant parfois des balises de fermeture manquantes, et ajoutera quelques balises supplémentaires pour le rendre correct.

Ceci est un exemple de dire à Nokogiri que le document en cours d’analyse est un fichier HTML complet, et que Nokogiri découvre qu’il ne l’est pas :

require 'nokogiri'

doc = Nokogiri::HTML('<body></body>')
puts doc.to_html 

Qui sort :

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body></body></html>

Notez que l’instruction DTD a été ajoutée, ainsi qu’une balise d’encapsulation <html>.

Si nous voulons éviter cela, nous pouvons analyser le document en tant que DocumentFragment :

require 'nokogiri'

doc = Nokogiri::HTML.fragment('<body></body>')
puts doc.to_html 

qui affiche désormais uniquement ce qui a été réellement transmis :

<body></body>

Il existe également une variante XML :

require 'nokogiri'

doc = Nokogiri::XML('<node />')
puts doc.to_xml

Qui sort :

<?xml version="1.0"?>
<node/>

et:

doc = Nokogiri::XML.fragment('<node />')
puts doc.to_xml

résultant en:

<node/>

Une variante plus détaillée de fragment consiste à utiliser DocumentFragment.parse, donc parfois vous le verrez écrit de cette façon.

De temps en temps, Nokogiri devra faire quelques corrections pour essayer de donner un sens au document :

doc = Nokogiri::XML::DocumentFragment.parse('<node ><foo/>')
puts doc.to_xml

Avec le code modifié étant maintenant :

<node>
  <foo/>
</node>

La même chose peut arriver avec HTML.

Parfois, le document est mutilé au-delà de la capacité de Nokogiri à le réparer, mais il essaiera quand même, ce qui aboutira à un document dont la hiérarchie a changé. Nokogiri ne déclenchera pas d’exception, mais il fournit un moyen de vérifier les erreurs et les actions qu’il a prises. Voir “https://www.wikiod.com/fr/nokogiri/demarrer-avec-nokogiri#Comment vérifier les erreurs d’analyse” pour plus d’informations.

Voir la documentation [Nokogiri::XML::ParseOptions][2] pour les différentes options utilisées lors de l’analyse.

[1] : http://www.nokogiri.org/tutorials/parsing_an_html_xml_document.html [2] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/ParseOptions

Comment vérifier les erreurs d’analyse

Nokogiri est un peu comme un navigateur, en ce sens qu’il tentera de fournir quelque chose d’utile même si le code HTML ou XML entrant est mal formé. Malheureusement, il le fait généralement en silence, mais nous pouvons demander une liste des erreurs en utilisant [errors][1] :

require 'nokogiri'

doc = Nokogiri::XML('<node><foo/>')
doc.errors
# => [#<Nokogiri::XML::SyntaxError: 1:13: FATAL: Premature end of data in tag node line 1>]

alors que le XML correct n’entraînerait aucune erreur :

doc = Nokogiri::XML('<node><foo/></node>')
doc.errors
# => []

Cela s’applique également à l’analyse HTML, mais, comme HTML est une forme détendue de XML, Nokogiri passera souvent par-dessus les nœuds finaux manquants et ne signalera que les nœuds malformés et d’autres erreurs pathologiques :

doc = Nokogiri::HTML('<html><body>')
doc.errors
# => []

doc = Nokogiri::HTML('<html><body><p')
doc.errors
# => [#<Nokogiri::XML::SyntaxError: 1:15: ERROR: Couldn't find end of Start Tag p>]

Si, après l’analyse, vous ne trouvez pas un nœud que vous pouvez voir dans votre éditeur, cela pourrait être la cause du problème. Parfois, il est utile de passer le code HTML via un formateur et de voir si l’imbrication aide à révéler le problème.

Et, parce que Nokogiri essaie de résoudre le problème mais parfois ne peut pas le faire correctement, parce que cela peut être une chose très difficile à faire pour le logiciel, nous devrons pré-traiter le fichier et retoucher les lignes avant de le remettre à Nokogiri. La façon de procéder dépend du fichier et du problème. Cela peut aller de la simple recherche d’un nœud et de l’ajout d’un > à la fin, à la suppression du balisage malformé intégré qui a été injecté par une mauvaise routine de grattage, c’est donc au programmeur de décider comment intervenir au mieux.

[1] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FDocument:errors

Comment extraire du texte d’un nœud ou de nœuds

Comment extraire correctement le texte des nœuds est l’une des questions les plus populaires que nous voyons, et est presque invariablement rendue plus difficile par une mauvaise utilisation des méthodes de “recherche” de Nokogiri.

Nokogiri prend en charge l’utilisation des sélecteurs CSS et XPath. Ceux-ci sont équivalents :

doc.at('p').text   # => "foo"
doc.at('//p').text # => "foo"

doc.search('p').size   # => 2
doc.search('//p').size # => 2

Les sélecteurs CSS sont [étendus avec de nombreuses extensions CSS de jQuery] [1] pour plus de commodité.

[at][2] et [search][3] sont des versions génériques de [at_css][4] et [at_xpath][5] avec [css][6] et [ xpath][7]. Nokogiri tente de déterminer si un sélecteur CSS ou XPath est transmis. Il est possible de créer un sélecteur qui trompe at ou search donc parfois il se méprendra, c’est pourquoi nous avons les versions plus spécifiques des méthodes . En général, j’utilise presque toujours les versions génériques et n’utilise la version spécifique que si je pense que Nokogiri comprendra mal. Cette pratique relève de la première entrée dans “[Trois vertus] [8]”.

Si vous recherchez un nœud spécifique et souhaitez son texte, utilisez at ou l’une de ses variantes at_css ou at_xpath :

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <p>foo</p>
    <p>bar</p>
  </body>
</html>
EOT

doc.at('p').text # => "foo"

at est équivalent à search(...).first, donc vous pourriez utiliser la version plus longue à taper, mais pourquoi ?

Si le texte extrait est concaténé après avoir utilisé search, css ou xpath, ajoutez map(&:text) au lieu d’utiliser simplement text :

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <p>foo</p>
    <p>bar</p>
  </body>
</html>
EOT

doc.search('p').text        # => "foobar"
doc.search('p').map(&:text) # => ["foo", "bar"]

Voir la documentation texte pour [NodeSet][9] et [Node][10] pour plus d’informations.

[1] : https://github.com/sparklemotion/nokogiri/wiki/From-jQuery [2] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FSearchable:at [3] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FSearchable:search [4] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FSearchable:at_css [5] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FSearchable:at_xpath [6] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FSearchable:css [7] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FSearchable:xpath [8] : http://threevirtues.com [9] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FNodeSet:inner_text [10] : http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri%2FXML%2FNode:content