Analisi HTML tramite Python


185

Sto cercando un modulo Parser HTML per Python che possa aiutarmi a ottenere i tag sotto forma di elenchi / dizionari / oggetti Python.

Se ho un documento del modulo:

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

quindi dovrebbe darmi un modo per accedere ai tag nidificati tramite il nome o l'id del tag HTML in modo che io possa sostanzialmente chiedergli di ottenere il contenuto / testo nel divtag con class='container'contenuto all'interno del bodytag o qualcosa di simile.

Se hai usato la funzione "Inspect element" di Firefox (vedi HTML) sapresti che ti dà tutti i tag in un bel modo annidato come un albero.

Preferirei un modulo integrato ma ciò potrebbe richiedere un po 'troppo.


Ho affrontato molte domande su Stack Overflow e alcuni blog su Internet e la maggior parte di essi suggerisce BeautifulSoup o lxml o HTMLParser, ma alcuni di questi dettagli descrivono la funzionalità e finiscono semplicemente come un dibattito su quale è più veloce / più efficace.


2
come tutti gli altri risponditori, consiglierei BeautifulSoup perché è davvero buono nella gestione di file HTML rotti.
Pascal Rosin,

Risposte:


195

In modo che io possa chiedergli di procurarmi il contenuto / testo nel tag div con class = 'container' contenuto nel tag body, o qualcosa di simile.

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)

Non hai bisogno di descrizioni delle prestazioni, immagino, basta leggere come funziona BeautifulSoup. Guarda la sua documentazione ufficiale .


2
Che cos'è esattamente l'oggetto parsed_html?
Sfogliando il

1
parsed_html è un oggetto BeautifulSoup, pensalo come un DOMElement o DOMDocument, tranne che ha proprietà "difficili", come "body" si riferirà all'oggetto BeautifulSoup (ricorda, in pratica è un nodo dell'albero) del primo (e in questo caso , solo) elemento body dell'elemento root (nel nostro caso, html)
Aadaam

18
Solo un aggiornamento: a partire da BeautifulSoup 4, la linea di importazione è orafrom bs4 import BeautifulSoup
Bailey Parker

2
Informazioni generali: se le prestazioni sono fondamentali, utilizzare meglio la lxmllibreria (vedere la risposta di seguito). Con cssselectciò è anche molto utile e le prestazioni sono spesso da 10 a 100 volte migliori rispetto alle altre librerie disponibili.
Lenar Hoyt

nota: l' classattributo è speciale:BeautifulSoup(html).find('div', 'container').text
jfs

85

Immagino che quello che stai cercando sia il pyquery :

pyquery: una libreria simile a jquery per Python.

Un esempio di ciò che vuoi potrebbe essere come:

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

E utilizza gli stessi selettori dell'elemento inspect di Firefox o Chrome. Per esempio:

il selettore di elementi è 'div # mw-head.noprint'

Il selettore dell'elemento ispezionato è 'div # mw-head.noprint'. Quindi in pyquery, devi solo passare questo selettore:

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

2
Ti amo 3000 per questo!
progyammer,

41

Qui puoi leggere di più sui diversi parser HTML in Python e sulle loro prestazioni. Anche se l'articolo è un po 'datato, ti dà comunque una buona panoramica.

Prestazioni del parser HTML Python

Consiglierei BeautifulSoup anche se non è integrato. Solo perché è così facile lavorare con questo tipo di attività. Per esempio:

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
Stavo cercando qualcosa che descrivesse le caratteristiche / funzionalità piuttosto che le prestazioni / l'efficienza. EDIT: Ci scusiamo per la risposta pre-matura, quel link è effettivamente buono. Grazie.
Sfogliando il

I primi tipi di elenco di punti riassumono le caratteristiche e le funzioni :)
Qiau,

5
Se usi BeautifulSoup4 (ultima versione):from bs4 import BeautifulSoup
Franck Dernoncourt

29

Rispetto alle altre librerie di parser lxmlè estremamente veloce:

E con cssselectè abbastanza facile da usare anche per raschiare pagine HTML:

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'))

Documentazione lxml.html


HTTPS non supportato
Sergio,

@Sergio uso import requests, Salva buffer di file: stackoverflow.com/a/14114741/1518921 (o urllib), dopo il carico di file salvati utilizzando parse,doc = parse('localfile.html').getroot()
Guilherme Nascimento

Analizzo enormi HTML per dati specifici. Farlo con BeautifulSoup ha richiesto un secondo 1.7, ma l'applicazione di lxml lo ha potenziato quasi *100più velocemente! Se ti preoccupi delle prestazioni, lxml è l'opzione migliore
Alex-Bogdanov,

9

Consiglio lxml per l'analisi dell'HTML. Vedi "Analisi HTML" (sul sito lxml).

Nella mia esperienza, Beautiful Soup incasina un po 'di HTML complesso. Credo che sia perché Beautiful Soup non è un parser, piuttosto un ottimo analizzatore di stringhe.


3
AIUI Beautiful Soup può essere fatto funzionare con la maggior parte dei parser XML "backend", lxml sembra essere uno dei parser supportati crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
ffledgling

@ffledgling Alcune funzioni di BeautifulSoup sono tuttavia piuttosto lente.
Lenar Hoyt

2

Consiglio di usare la libreria justext :

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

Utilizzo: 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

Vorrei usare EHP

https://github.com/iogf/ehp

Ecco qui:

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()

Produzione:

Something here
Something else

5
Spiega per favore. Cosa useresti EHP sul popolare BeautifulSoup o lxml?
ChaimG,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.