Parsing HTML menggunakan Python

185

Saya mencari modul HTML Parser untuk Python yang dapat membantu saya mendapatkan tag dalam bentuk daftar Python / kamus / objek.

Jika saya memiliki dokumen formulir:

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

maka itu harus memberi saya cara untuk mengakses tag bersarang melalui nama atau id dari tag HTML sehingga saya pada dasarnya dapat meminta saya untuk mendapatkan saya konten / teks dalam divtag dengan yang class='container'terkandung dalam bodytag, atau sesuatu yang serupa.

Jika Anda telah menggunakan fitur "Inspect element" Firefox (lihat HTML), Anda akan tahu bahwa itu memberi Anda semua tag dengan cara bersarang yang bagus seperti pohon.

Saya lebih suka modul built-in tapi itu mungkin meminta sedikit terlalu banyak.


Saya telah melalui banyak pertanyaan tentang Stack Overflow dan beberapa blog di internet dan kebanyakan dari mereka menyarankan BeautifulSoup atau lxml atau HTMLParser tetapi sedikit dari rincian ini fungsionalitas dan hanya berakhir sebagai sebuah debat mengenai mana yang lebih cepat / lebih efisien.

meraba-raba
sumber
2
seperti semua penjawab lainnya, saya akan merekomendasikan BeautifulSoup karena sangat bagus dalam menangani file HTML yang rusak.
Pascal Rosin

Jawaban:

195

Sehingga saya bisa memintanya untuk memberi saya konten / teks dalam tag div dengan class = 'container' yang terkandung di dalam tag body, Atau yang serupa.

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)

Anda tidak perlu deskripsi kinerja, saya kira - baca saja cara kerja BeautifulSoup. Lihatlah dokumentasi resminya .

Aadaam
sumber
2
Apa sebenarnya objek parsed_html?
meraba
1
parsed_html adalah objek BeautifulSoup, pikirkan itu seperti DOMElement atau DOMDocument, kecuali ia memiliki properti "rumit", seperti "tubuh" akan merujuk ke objek BeautifulSoup (ingat, pada dasarnya simpul pohon) dari yang pertama (dan dalam kasus ini , hanya) elemen tubuh dari elemen root (dalam kasus kami, html)
Aadaam
18
Hanya pembaruan: pada BeautifulSoup 4, jalur impor sekarangfrom bs4 import BeautifulSoup
Bailey Parker
2
Info umum: Jika kinerja sangat penting, lebih baik gunakan lxmlperpustakaan sebagai gantinya (lihat jawaban di bawah). Dengan cssselectitu juga cukup berguna dan kinerja seringkali 10 hingga 100 kali lipat lebih baik daripada perpustakaan lain yang tersedia.
Lenar Hoyt
note: classatribut spesial:BeautifulSoup(html).find('div', 'container').text
jfs
85

Saya kira yang Anda cari adalah pyquery :

pyquery: perpustakaan seperti jquery untuk python.

Contoh dari apa yang Anda inginkan mungkin seperti:

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

Dan ia menggunakan penyeleksi yang sama dengan elemen inspeksi Firefox atau Chrome. Sebagai contoh:

pemilih elemen adalah 'div # mw-head.noprint'

Pemilih elemen yang diperiksa adalah 'div # mw-head.noprint'. Jadi dalam pyquery, Anda hanya perlu melewati pemilih ini:

pq('div#mw-head.noprint')
YusuMishi
sumber
2
Aku mencintaimu 3000 untuk ini!
Progyammer
41

Di sini Anda dapat membaca lebih lanjut tentang parser HTML berbeda di Python dan kinerjanya. Meskipun artikelnya sedikit bertanggal, artikel ini tetap memberi Anda gambaran yang bagus.

Kinerja pengurai Python HTML

Saya akan merekomendasikan BeautifulSoup meskipun tidak built-in. Hanya karena begitu mudah untuk bekerja dengan jenis tugas itu. Misalnya:

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
sumber
2
Saya mencari sesuatu yang merinci fitur / fungsi daripada kinerja / efisiensi. EDIT: Maaf untuk jawaban sebelum dewasa, tautan itu sebenarnya bagus. Terima kasih.
meraba
Jenis daftar poin pertama merangkum fitur dan fungsi :)
Qiau
5
Jika Anda menggunakan BeautifulSoup4 (versi terbaru):from bs4 import BeautifulSoup
Franck Dernoncourt
29

Dibandingkan dengan parser libraries lainnya lxmlsangat cepat:

Dan dengan cssselectitu cukup mudah digunakan untuk memo halaman HTML juga:

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 Dokumentasi

Lenar Hoyt
sumber
HTTPS tidak didukung
Sergio
@Sergio gunakan import requests, simpan buffer ke file: stackoverflow.com/a/14114741/1518921 (atau urllib), setelah memuat file yang disimpan menggunakan parse,doc = parse('localfile.html').getroot()
Guilherme Nascimento
Saya mem-parsing HTML besar untuk data tertentu. Melakukannya dengan BeautifulSoup memerlukan waktu sebentar1.7 , tetapi menerapkan lxml sebagai gantinya, meningkatkannya hampir *100kali LEBIH CEPAT! Jika peduli dengan kinerja, lxml adalah pilihan terbaik
Alex-Bogdanov
9

Saya merekomendasikan lxml untuk parsing HTML. Lihat "Parsing HTML" (di situs lxml).

Dalam pengalaman saya, Beautiful Soup mengacaukan beberapa HTML yang rumit. Saya percaya itu karena Beautiful Soup bukan parser, melainkan penganalisa string yang sangat baik.

Cinta dan kedamaian - Joe Codeswell
sumber
3
AIUI Beautiful Soup dapat dibuat untuk bekerja dengan sebagian besar parser XML "backend", lxml tampaknya menjadi salah satu parser yang didukung crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
ffledgling
@ffledgling Namun beberapa fungsi BeautifulSoup cukup lamban.
Lenar Hoyt
2

Saya sarankan menggunakan perpustakaan justext :

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

Penggunaan: 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
sumber
0

Saya akan menggunakan EHP

https://github.com/iogf/ehp

Ini dia:

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

Keluaran:

Something here
Something else
Prajurit Tidak Dikenal
sumber
5
Tolong jelaskan. Apa yang akan Anda gunakan EHP di atas BeautifulSoup atau lxml yang populer?
ChaimG