Analizowanie HTML za pomocą Pythona

185

Szukam modułu parsera HTML dla Pythona, który może pomóc mi uzyskać tagi w postaci list / słowników / obiektów Pythona.

Jeśli mam dokument w formie:

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

to powinno dać mi dostęp do zagnieżdżonych tagów poprzez nazwę lub identyfikator tagu HTML, tak że mogę w zasadzie poprosić go o przesłanie zawartości / tekstu do divtagu class='container'zawierającego się w bodytagu lub coś podobnego.

Jeśli używałeś funkcji Firefox „Inspect element” (zobacz HTML), wiedziałbyś, że daje ci wszystkie tagi w ładnie zagnieżdżony sposób, jak drzewo.

Wolałbym wbudowany moduł, ale może to wymagać trochę za dużo.


Przeszedłem wiele pytań na temat przepełnienia stosu i kilka blogów w Internecie, a większość z nich sugeruje BeautifulSoup lub lxml lub HTMLParser, ale kilka z nich szczegółowo opisuje funkcjonalność i po prostu kończy się debatą, która z nich jest szybsza / bardziej wydajna.

bawiłem się
źródło
2
podobnie jak wszyscy inni użytkownicy odpowiadający, poleciłbym BeautifulSoup, ponieważ naprawdę dobrze radzi sobie z uszkodzonymi plikami HTML.
Pascal Rosin

Odpowiedzi:

195

Tak, że mogę poprosić go o przesłanie mi treści / tekstu do znacznika div z class = 'container' zawartym w znaczniku body lub coś podobnego.

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)

Chyba nie potrzebujesz opisów wydajności - po prostu przeczytaj, jak działa BeautifulSoup. Spójrz na jego oficjalną dokumentację .

Aadaam
źródło
2
Czym dokładnie jest obiekt parsowany_html?
ffledgling
1
parsed_html jest obiektem BeautifulSoup, pomyśl o nim jak o DOMElement lub DOMDocument, z tym wyjątkiem, że ma właściwości „trudne”, np. „body” będzie odnosić się do obiektu BeautifulSoup (pamiętaj, że jest to w zasadzie węzeł drzewa) pierwszego (iw tym przypadku , tylko) element body elementu root (w naszym przypadku html)
Aadaam
18
Tylko aktualizacja: od BeautifulSoup 4 linia importu jest terazfrom bs4 import BeautifulSoup
Bailey Parker
2
Informacje ogólne: Jeśli wydajność ma kluczowe znaczenie, lepiej lxmlzamiast tego użyj biblioteki (patrz odpowiedź poniżej). Ze cssselectjest to bardzo przydatne również i wydajność jest często 10- do 100-krotnie lepiej niż w innych dostępnych bibliotek.
Lenar Hoyt,
Uwaga: classatrybut jest specjalny:BeautifulSoup(html).find('div', 'container').text
jfs
85

Myślę, że szukasz piractwa :

pyquery: biblioteka podobna do jquery dla Pythona.

Przykładem tego, co chcesz, może być:

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

I używa tych samych selektorów, co element kontrolny przeglądarki Firefox lub Chrome. Na przykład:

selektor elementów to „div # mw-head.noprint”

Selektem sprawdzanego elementu jest „div # mw-head.noprint”. Tak więc w pirotechnice wystarczy przekazać ten selektor:

pq('div#mw-head.noprint')
YusuMishi
źródło
2
Kocham cię za to 3000!
progyammer
41

Tutaj możesz przeczytać więcej o różnych parserach HTML w Pythonie i ich wydajności. Mimo że artykuł jest nieco przestarzały, nadal daje dobry przegląd.

Wydajność parsera HTML w Pythonie

Polecam BeautifulSoup, mimo że nie jest wbudowana. Tylko dlatego, że tak łatwo jest pracować z tego rodzaju zadaniami. Na przykład:

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
Qiau
źródło
2
Szukałem czegoś, co bardziej szczegółowo opisuje cechy / funkcjonalność niż wydajność / wydajność. EDYCJA: Przepraszam za wcześniejszą odpowiedź, ten link jest naprawdę dobry. Dzięki.
ffledgling
Pierwsze rodzaje list punktowych podsumowują funkcje i funkcje :)
Qiau,
5
Jeśli używasz BeautifulSoup4 (najnowsza wersja):from bs4 import BeautifulSoup
Franck Dernoncourt
29

W porównaniu z innymi bibliotekami parsera lxmljest niezwykle szybki:

A dzięki cssselectdość łatwemu w użyciu również do skrobania stron 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'))

lxml.html Dokumentacja

Lenar Hoyt
źródło
HTTPS nieobsługiwany
Sergio
@ Użyjergio import requests, zapisz bufor do pliku: stackoverflow.com/a/14114741/1518921 (lub urllib), po załadowaniu zapisanego pliku za pomocą parsowania,doc = parse('localfile.html').getroot()
Guilherme Nascimento
Analizuję ogromne HTML dla określonych danych. Robienie tego z BeautifulSoup trwało 1.7sekundę, ale zastosowanie lxml zamiast tego przyspieszyło go prawie *100razy SZYBCIEJ! Jeśli zależy Ci na wydajności, najlepszym rozwiązaniem jest lxml
Alex-Bogdanov
9

Polecam lxml do analizowania HTML. Zobacz „Analiza składni HTML” (na stronie lxml).

Z mojego doświadczenia wynika, że ​​Beautiful Soup nie działa na skomplikowanym HTML. Uważam, że dzieje się tak, ponieważ Piękna Zupa nie jest parserem, a raczej bardzo dobrym analizatorem strun.

Miłość i pokój - Joe Codeswell
źródło
3
AIUI Beautiful Soup może być przystosowana do pracy z większością parserów XML „backendowych”, lxml wydaje się być jednym z obsługiwanych parserów crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
ffledgling
@ffledgling Niektóre funkcje BeautifulSoup są jednak dość powolne.
Lenar Hoyt
2

Polecam użycie biblioteki justext :

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

Zastosowanie: 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)
Wesam Na
źródło
0

Użyłbym EHP

https://github.com/iogf/ehp

Oto on:

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

Wynik:

Something here
Something else
Nieznany żołnierz
źródło
5
Proszę wytłumacz. Czego użyłbyś EHP w stosunku do popularnej BeautifulSoup lub lxml?
ChaimG