Analyse HTML à l'aide de Python


185

Je recherche un module d'analyse HTML pour Python qui peut m'aider à obtenir les balises sous la forme de listes / dictionnaires / objets Python.

Si j'ai un document du formulaire:

<html>
<head>Heading</head>
<body attr1='val1'>
    <div class='container'>
        <div id='class'>Something here</div>
        <div>Something else</div>
    </div>
</body>
</html>

alors cela devrait me donner un moyen d'accéder aux balises imbriquées via le nom ou l'identifiant de la balise HTML afin que je puisse fondamentalement lui demander de m'obtenir le contenu / texte de la divbalise avec class='container'contenu dans la bodybalise, ou quelque chose de similaire.

Si vous avez utilisé la fonction "Inspecter l'élément" de Firefox (voir HTML), vous savez qu'elle vous donne toutes les balises d'une manière bien imbriquée comme un arbre.

Je préférerais un module intégré, mais cela pourrait demander un peu trop.


J'ai traversé beaucoup de questions sur Stack Overflow et quelques blogs sur Internet et la plupart d'entre eux suggèrent BeautifulSoup ou lxml ou HTMLParser mais peu d'entre eux détaillent la fonctionnalité et se terminent simplement par un débat sur lequel est le plus rapide / le plus efficace.


2
comme tous les autres répondeurs, je recommanderais BeautifulSoup car il est vraiment bon pour gérer les fichiers HTML cassés.
Pascal Rosin

Réponses:


195

Pour que je puisse lui demander de me fournir le contenu / texte dans la balise div avec class = 'container' contenu dans la balise body, Ou quelque chose de similaire.

try: 
    from BeautifulSoup import BeautifulSoup
except ImportError:
    from bs4 import BeautifulSoup
html = #the HTML code you've written above
parsed_html = BeautifulSoup(html)
print(parsed_html.body.find('div', attrs={'class':'container'}).text)

Vous n'avez pas besoin de descriptions de performances, je suppose - lisez simplement comment fonctionne BeautifulSoup. Regardez sa documentation officielle .


2
Qu'est-ce que l'objet parsed_html exactement?
ffledgling

1
parsed_html est un objet BeautifulSoup, pensez-y comme un DOMElement ou DOMDocument, sauf qu'il a des propriétés "délicates", comme "body" fera référence à l'objet BeautifulSoup (rappelez-vous, c'est un nœud d'arbre en gros) du premier (et dans ce cas , uniquement) élément du corps de l'élément racine (dans notre cas, html)
Aadaam

18
Juste une mise à jour: à partir de BeautifulSoup 4, la ligne d'importation est maintenantfrom bs4 import BeautifulSoup
Bailey Parker

2
Informations générales: si les performances sont essentielles, utilisez lxmlplutôt la bibliothèque (voir la réponse ci-dessous). Avec cssselectil est très utile aswell et la performance est souvent de 10 à 100 fois mieux que les autres bibliothèques disponibles.
Lenar Hoyt

note: l' classattribut est spécial:BeautifulSoup(html).find('div', 'container').text
jfs

85

Je suppose que vous recherchez pyquery :

pyquery: une bibliothèque de type jquery pour python.

Un exemple de ce que vous voulez peut être:

from pyquery import PyQuery    
html = # Your HTML CODE
pq = PyQuery(html)
tag = pq('div#id') # or     tag = pq('div.class')
print tag.text()

Et il utilise les mêmes sélecteurs que l'élément inspect de Firefox ou Chrome. Par exemple:

le sélecteur d'élément est 'div # mw-head.noprint'

Le sélecteur d'élément inspecté est 'div # mw-head.noprint'. Donc dans pyquery, il vous suffit de passer ce sélecteur:

pq('div#mw-head.noprint')

2
Je t'aime 3000 pour ça!
progyammer

41

Ici, vous pouvez en savoir plus sur les différents analyseurs HTML en Python et leurs performances. Même si l'article est un peu daté, il vous donne quand même un bon aperçu.

Performances de l'analyseur HTML Python

Je recommanderais BeautifulSoup même s'il n'est pas intégré. Juste parce qu'il est si facile de travailler avec pour ce genre de tâches. Par exemple:

import urllib2
from BeautifulSoup import BeautifulSoup

page = urllib2.urlopen('http://www.google.com/')
soup = BeautifulSoup(page)

x = soup.body.find('div', attrs={'class' : 'container'}).text

2
Je cherchais quelque chose qui détaille les caractéristiques / fonctionnalités plutôt que les performances / efficacité. EDIT: Désolé pour la réponse prématurée, ce lien est en fait bon. Merci.
ffledgling le

Les premiers types de liste de points résument les caractéristiques et les fonctions :)
Qiau

5
Si vous utilisez BeautifulSoup4 (dernière version):from bs4 import BeautifulSoup
Franck Dernoncourt

29

Par rapport aux autres bibliothèques d'analyseurs, lxmlc'est extrêmement rapide:

Et avec cssselectc'est assez facile à utiliser pour gratter des pages HTML aussi:

from lxml.html import parse
doc = parse('http://www.google.com').getroot()
for div in doc.cssselect('a'):
    print '%s: %s' % (div.text_content(), div.get('href'))

Documentation lxml.html


HTTPS non pris en charge
Sergio

@Sergio use import requests, enregistrez le tampon dans un fichier: stackoverflow.com/a/14114741/1518921 (ou urllib), après avoir chargé le fichier enregistré à l'aide de parse,doc = parse('localfile.html').getroot()
Guilherme Nascimento

J'analyse d'énormes HTML pour des données spécifiques. Le faire avec BeautifulSoup a pris quelques 1.7secondes, mais l'application de lxml à la place l'a boosté presque *100fois plus vite ! Si vous vous souciez de la performance, lxml est la meilleure option
Alex-Bogdanov

9

Je recommande lxml pour analyser le HTML. Voir "Analyse HTML" (sur le site lxml).

D'après mon expérience, Beautiful Soup gâche un code HTML complexe. Je pense que c'est parce que Beautiful Soup n'est pas un analyseur, mais plutôt un très bon analyseur de cordes.


3
AIUI Beautiful Soup peut être fait pour fonctionner avec la plupart des analyseurs XML "backend", lxml semble être l'un des analyseurs pris en charge crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
ffledgling

@ffledgling Certaines fonctions de BeautifulSoup sont cependant assez lentes.
Lenar Hoyt

2

Je recommande d'utiliser la bibliothèque justext :

https://github.com/miso-belica/jusText

Utilisation: Python2:

import requests
import justext

response = requests.get("http://planet.python.org/")
paragraphs = justext.justext(response.content, justext.get_stoplist("English"))
for paragraph in paragraphs:
    print paragraph.text

Python3:

import requests
import justext

response = requests.get("http://bbc.com/")
paragraphs = justext.justext(response.content, justext.get_stoplist("English"))
for paragraph in paragraphs:
    print (paragraph.text)

0

J'utiliserais EHP

https://github.com/iogf/ehp

C'est ici:

from ehp import *

doc = '''<html>
<head>Heading</head>
<body attr1='val1'>
    <div class='container'>
        <div id='class'>Something here</div>
        <div>Something else</div>
    </div>
</body>
</html>
'''

html = Html()
dom = html.feed(doc)
for ind in dom.find('div', ('class', 'container')):
    print ind.text()

Production:

Something here
Something else

5
S'il vous plaît, expliquez. Qu'utiliseriez-vous EHP sur le populaire BeautifulSoup ou lxml?
ChaimG
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.