Phân tích cú pháp HTML bằng Python


185

Tôi đang tìm kiếm một mô-đun phân tích cú pháp HTML cho Python có thể giúp tôi lấy các thẻ ở dạng danh sách / từ điển / đối tượng Python.

Nếu tôi có một tài liệu của mẫu:

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

sau đó nó sẽ cho tôi một cách để truy cập các thẻ lồng nhau thông qua tên hoặc id của thẻ HTML để tôi có thể yêu cầu nó lấy nội dung / văn bản trong divthẻ có class='container'trong bodythẻ hoặc một cái gì đó tương tự.

Nếu bạn đã sử dụng tính năng "Kiểm tra phần tử" của Firefox (xem HTML), bạn sẽ biết rằng nó cung cấp cho bạn tất cả các thẻ theo cách lồng nhau đẹp như một cái cây.

Tôi thích một mô-đun tích hợp nhưng điều đó có thể đòi hỏi quá nhiều.


Tôi đã xem qua rất nhiều câu hỏi về Stack Overflow và một vài blog trên internet và hầu hết trong số họ đề xuất BeautifulSoup hoặc lxml hoặc HTMLParser nhưng một vài trong số đó chi tiết về chức năng và đơn giản là kết thúc như một cuộc tranh luận về việc cái nào nhanh hơn / hiệu quả hơn.


2
Giống như tất cả những người trả lời khác, tôi muốn giới thiệu BeautifulSoup vì nó thực sự tốt trong việc xử lý các tệp HTML bị hỏng.
Pascal Rosin

Câu trả lời:


195

Vì vậy, tôi có thể yêu cầu nó lấy cho tôi nội dung / văn bản trong thẻ div với class = 'container' có trong thẻ body, Hoặc một cái gì đó tương tự.

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)

Bạn không cần mô tả hiệu suất tôi đoán - chỉ cần đọc cách BeautifulSoup hoạt động. Nhìn vào tài liệu chính thức của nó .


2
Chính xác thì đối tượng Parsed_html là gì?
ffledgling

1
Parsed_html là một đối tượng BeautifulSoup, hãy nghĩ về nó như một DOMEuity hoặc DOMDocument, ngoại trừ nó có các thuộc tính "khó hiểu", như "body" sẽ đề cập đến đối tượng BeautifulSoup (về cơ bản, đó là một nút cây) , chỉ) phần tử cơ thể của phần tử gốc (trong trường hợp của chúng tôi, html)
Aadaam

18
Chỉ là một bản cập nhật: kể từ BeautifulSoup 4, dòng nhập khẩu hiện tạifrom bs4 import BeautifulSoup
Bailey Parker

2
Thông tin chung: Nếu hiệu suất là quan trọng, lxmlthay vào đó hãy sử dụng thư viện (xem câu trả lời bên dưới). Với cssselectnó khá hữu ích và hiệu suất thường tốt hơn 10 đến 100 lần so với các thư viện khác có sẵn.
Lenar Hoyt

lưu ý: classthuộc tính là đặc biệt:BeautifulSoup(html).find('div', 'container').text
jfs

85

Tôi đoán những gì bạn đang tìm kiếm là pyquery :

pyquery: một thư viện giống như jquery cho python.

Một ví dụ về những gì bạn muốn có thể giống như:

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

Và nó sử dụng các bộ chọn tương tự như phần tử kiểm tra của Firefox hoặc Chrome. Ví dụ:

bộ chọn phần tử là 'div # mw-head.noprint'

Bộ chọn phần tử được kiểm tra là 'div # mw-head.noprint'. Vì vậy, trong pyquery, bạn chỉ cần vượt qua bộ chọn này:

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

2
Tôi yêu bạn 3000 vì điều này!
progyammer

41

Tại đây bạn có thể đọc thêm về các trình phân tích cú pháp HTML khác nhau trong Python và hiệu suất của chúng. Mặc dù bài viết có một chút ngày nhưng nó vẫn cung cấp cho bạn một cái nhìn tổng quan tốt.

Hiệu suất trình phân tích cú pháp HTML của Python

Tôi muốn giới thiệu BeautifulSoup mặc dù nó không được tích hợp. Chỉ vì nó rất dễ làm việc với những loại nhiệm vụ đó. Ví dụ:

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
Tôi đang tìm kiếm một cái gì đó chi tiết các tính năng / chức năng hơn là hiệu suất / hiệu quả. EDIT: Xin lỗi vì câu trả lời trước khi trưởng thành, liên kết đó thực sự tốt. Cảm ơn.
ffledgling

Các loại danh sách điểm đầu tiên tóm tắt các tính năng và chức năng :)
Qiau

5
Nếu bạn sử dụng BeautifulSoup4 (phiên bản mới nhất):from bs4 import BeautifulSoup
Franck Dernoncourt

29

So với các thư viện phân tích cú pháp khác lxmllà cực kỳ nhanh:

Và với cssselectnó cũng khá dễ sử dụng để quét các trang 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 Tài liệu


HTTPS không được hỗ trợ
Sergio

@Sergio sử dụng import requests, lưu bộ đệm vào tệp: stackoverflow.com/a/14114741/1518921 (hoặc urllib), sau khi tải tệp đã lưu bằng parse,doc = parse('localfile.html').getroot()
Guilherme Nascimento

Tôi phân tích các HTML lớn cho một dữ liệu cụ thể. Làm điều đó với BeautifulSoup mất vài 1.7giây, nhưng thay vào đó, áp dụng lxml , đã tăng nó gần *100gấp nhiều lần! Nếu quan tâm đến hiệu suất, lxml là lựa chọn tốt nhất
Alex-Bogdanov

9

Tôi khuyên dùng lxml để phân tích cú pháp HTML. Xem "Phân tích cú pháp HTML" (trên trang web lxml).

Theo kinh nghiệm của tôi, Soup đẹp làm rối tung một số HTML phức tạp. Tôi tin rằng đó là vì Beautiful Soup không phải là một trình phân tích cú pháp, mà là một công cụ phân tích chuỗi rất tốt.


3
AIUI Beautiful Soup có thể được tạo để hoạt động với hầu hết các trình phân tích cú pháp XML "phụ trợ", lxml dường như là một trong những trình phân tích cú pháp được hỗ trợ crummy.com/software/BeautitableSoup/bs4/doc/#installing-a-parser
ffledgling

@ffledgling Một số chức năng của BeautifulSoup khá chậm chạp.
Lenar Hoyt

2

Tôi khuyên bạn nên sử dụng justext thư viện :

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

Cách sử dụng: 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

Tôi sẽ sử dụng EHP

https://github.com/iogf/ehp

Đây là:

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

Đầu ra:

Something here
Something else

5
Vui lòng giải thích. Bạn sẽ sử dụng EHP gì trên BeautifulSoup hoặc lxml phổ biến?
ChaimG
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.