2010-04-03 6 views
2

J'essaye d'analyser certains html retournés (à partir de http://www.google.com/movies?near=37130) pour rechercher des films en cours de lecture. Le modèle que j'essaie de faire correspondre ressemble à:
<span dir=ltr>Clash of the Titans</span>ruby ​​regex, analyse html

Parmi lesquels il y en a plusieurs dans le code HTML retourné.

Je suis en train obtenir un tableau des titres de films avec la commande suivante:
titles = listings_html.split(/(<span dir=ltr>).*(<\/span>)/)

Mais je ne reçois pas les résultats que je me attends. Quelqu'un peut-il voir un problème avec mon approche ou regex?

+1

S'il vous plaît voir http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 –

+3

En outre, cette question pourrait être la question la moins bien formatée déjà! –

+0

La chose est, quelqu'un salope toujours si je ne poste pas chaque petit commentaire dans le code. Donc j'essayais juste d'éviter ça. – danwoods

Répondre

5

Verey Bad est généralement considéré pour analyser HTML avec RegExs puisque HTML n'a pas de grammaire régulière. Voir la liste des liens aux explications (certains de SO) here.

Vous devriez plutôt utiliser une bibliothèque HTML désignée, such as this

3

parser HTML avec Ruby, utilisez Nokogiri ou hpricot.

+0

J'utiliserais certainement hpricot, c'est vraiment facile à utiliser. Il y a une bonne documentation dans le readme ici http://github.com/whymirror/hpricot – Jamie

+0

Et j'utiliserais sûrement Nokogiri parce qu'il était capable de gérer des données XML malformées sur lesquelles hpricot a vomi. :-) http://nokogiri.org/ –

+0

@Jamie, des deux, je recommanderais Nokogiri, aussi. –

4

Je n'ai pas lu tout le code que vous avez posté car il m'a brûlé les yeux.

<span>.*</span> 

Cette regex correspond <span>hello</span> correctement, mais échoue à <span>hello</span><span>there</span> et correspond à la chaîne entière. Rappelez-vous que l'opérateur * est gourmand, il correspond donc à la plus longue chaîne possible. Vous pouvez le rendre non-gourmand en utilisant .*? devrait le faire fonctionner.

Toutefois, il n'est pas judicieux d'utiliser des expressions régulières pour analyser le code HTML.

1- Vous ne pouvez pas toujours analyser HTML avec regex. Le HTML n'est pas régulier.

2- Il est très difficile d'écrire ou de maintenir une regex.

3- Il est facile de casser l'expression régulière en utilisant une entrée comme <span><a href="</span>"></a></span>.

2

(il ne semble pas que le code HTML exemple vous mis en ligne a fait des exemples du modèle que vous essayez de faire correspondre.)

Alicia est exact que regex contre html est généralement une mauvaise idée, et comme vos besoins deviennent plus complexes, ils vont tomber en panne.

Cela dit, votre exemple est assez simple ..

doc.scan(/<span dir=ltr>(.*)<\/span/) do |match| 
    puts match    
end 

Comme mentionné précédemment,. * Est généralement gourmand (et je devrait rendre compte de cela), mais il semble que, lorsqu'il est utilisé à l'intérieur de balayage, vous n'obtenez pas de comportement cupide. J'ai été capable de faire correspondre plusieurs de ces modèles dans un seul document.