การแยก HTML โดยใช้ Python


185

ฉันกำลังมองหาโมดูล HTML Parser สำหรับ Python ที่สามารถช่วยให้ฉันได้รับแท็กในรูปแบบของรายการ / พจนานุกรม / วัตถุ Python

ถ้าฉันมีเอกสารของแบบฟอร์ม:

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

จากนั้นควรให้วิธีเข้าถึงแท็กที่ซ้อนกันผ่านชื่อหรือรหัสของแท็ก HTML เพื่อให้ฉันสามารถขอให้ฉันรับเนื้อหา / ข้อความในdivแท็กที่มีclass='container'อยู่ภายในbodyแท็กหรือสิ่งที่คล้ายกัน

หากคุณใช้ฟีเจอร์ "ตรวจสอบองค์ประกอบ" ของ Firefox (ดู HTML) คุณจะรู้ว่ามันให้แท็กทั้งหมดในลักษณะซ้อนกันอย่างดีเช่นต้นไม้

ฉันต้องการโมดูลในตัว แต่อาจจะขอมากไปหน่อย


ฉันได้อ่านคำถามมากมายเกี่ยวกับ Stack Overflow และบล็อกบางส่วนบนอินเทอร์เน็ตและส่วนใหญ่แนะนำให้ BeautifulSoup หรือ lxml หรือ HTMLParser แต่รายละเอียดเหล่านี้มีเพียงเล็กน้อยและจบลงด้วยการอภิปรายว่าอันไหนเร็วกว่ากัน


2
เช่นเดียวกับผู้ตอบคำถามอื่น ๆ ฉันขอแนะนำ BeautifulSoup เพราะมันดีในการจัดการไฟล์ HTML ที่เสียหาย
Pascal Rosin

คำตอบ:


195

เพื่อให้ฉันสามารถขอให้ฉันรับเนื้อหา / ข้อความในแท็ก div ที่มี class = 'container' ที่บรรจุอยู่ภายในแท็ก body หรือสิ่งที่คล้ายกัน

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)

คุณไม่ต้องการคำอธิบายเกี่ยวกับประสิทธิภาพฉันเดาว่าแค่อ่านว่า BeautifulSoup ทำงานอย่างไร ดูของเอกสารที่เป็นทางการ


2
วัตถุ parsed_html คืออะไร
ffledgling

1
parsed_html เป็นวัตถุ BeautifulSoup คิดเหมือน DOMElement หรือ DOMDocument ยกเว้นว่ามีคุณสมบัติ "หากิน" เช่น "ร่างกาย" จะอ้างถึงวัตถุ BeautifulSoup (จำไว้ว่ามันเป็นโหนดต้นไม้โดยทั่วไป) ของแรก (และในกรณีนี้ เท่านั้น) องค์ประกอบขององค์ประกอบราก (ในกรณีของเรา, html)
Aadaam

18
เพียงแค่อัปเดต: ตั้งแต่วันที่ BeautifulSoup 4 สายการนำเข้าอยู่ในขณะนี้from bs4 import BeautifulSoup
Bailey Parker

2
ข้อมูลทั่วไป: หากประสิทธิภาพมีความสำคัญควรใช้lxmlห้องสมุดแทน (ดูคำตอบด้านล่าง) ด้วยcssselectมันค่อนข้างมีประโยชน์เช่นกันและประสิทธิภาพมักดีกว่าห้องสมุดอื่น ๆ ที่มีอยู่ 10 ถึง 100 เท่า
Lenar Hoyt

หมายเหตุ: classแอตทริบิวต์เป็นพิเศษ:BeautifulSoup(html).find('div', 'container').text
jfs

85

ผมคิดว่าสิ่งที่คุณกำลังมองหาpyquery :

pyquery: ไลบรารีที่เหมือน jquery สำหรับ python

ตัวอย่างของสิ่งที่คุณต้องการอาจเป็นเช่น:

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

และใช้ตัวเลือกเดียวกับองค์ประกอบการตรวจสอบของ Firefox หรือ Chrome ตัวอย่างเช่น:

ตัวเลือกองค์ประกอบคือ 'div # mw-head.noprint'

ตัวเลือกองค์ประกอบที่ตรวจสอบคือ 'div # mw-head.noprint' ดังนั้นใน pyquery คุณเพียงแค่ผ่านตัวเลือกนี้:

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

2
ฉันรักคุณ 3000 สำหรับสิ่งนี้!
progyammer

41

ที่นี่คุณสามารถอ่านเพิ่มเติมเกี่ยวกับตัวแยกวิเคราะห์ HTML ต่างๆใน Python และประสิทธิภาพได้ แม้ว่าบทความนั้นจะค่อนข้างล้าสมัย แต่ก็ยังให้ภาพรวมที่ดีแก่คุณ

ตัวแยกวิเคราะห์ Python HTML

ฉันอยากแนะนำ BeautifulSoup ถึงแม้ว่ามันจะไม่ได้สร้างขึ้นมาเพราะมันง่ายที่จะทำงานกับงานประเภทนั้น เช่น:

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
ฉันกำลังมองหาสิ่งที่มีรายละเอียดคุณสมบัติ / ฟังก์ชั่นมากกว่าประสิทธิภาพ / ประสิทธิภาพ แก้ไข: ขออภัยสำหรับคำตอบก่อนผู้ใหญ่ลิงก์นั้นดีจริง ขอบคุณ
ffledgling

ครั้งแรกชนิดจุดรายการสรุปคุณสมบัติและฟังก์ชั่น :)
Qiau

5
หากคุณใช้ BeautifulSoup4 (เวอร์ชั่นล่าสุด):from bs4 import BeautifulSoup
Franck Dernoncourt

29

เมื่อเทียบกับ parser library อื่น ๆlxmlนั้นเร็วมาก:

และcssselectใช้งานง่ายสำหรับการขูดหน้า 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 เอกสารประกอบ


ไม่รองรับ HTTPS
Sergio

@Sergio ใช้import requestsบันทึกบัฟเฟอร์ลงในไฟล์: stackoverflow.com/a/14114741/1518921 (หรือ urllib) หลังจากโหลดไฟล์ที่บันทึกไว้โดยใช้การวิเคราะห์doc = parse('localfile.html').getroot()
Guilherme Nascimento

ฉันแยกวิเคราะห์ HTML ขนาดใหญ่สำหรับข้อมูลเฉพาะ การใช้BeautifulSoupใช้เวลาสักครู่1.7แต่ใช้lxmlแทนเพิ่มแรงขึ้นเกือบ*100เท่าเร็วกว่า! หากสนใจเกี่ยวกับประสิทธิภาพlxmlเป็นตัวเลือกที่ดีที่สุด
Alex-Bogdanov

9

ฉันแนะนำlxmlสำหรับการแยกวิเคราะห์ HTML ดู"การแยก HTML" (บนไซต์ lxml)

ในประสบการณ์ของฉัน Beautiful Soup สับสนกับ HTML ที่ซับซ้อนบางอย่าง ฉันเชื่อว่าเป็นเพราะ Beautiful Soup ไม่ใช่ตัวแยกวิเคราะห์ แต่เป็นตัววิเคราะห์สตริงที่ดีมาก


3
AIUI สวยซุปสามารถทำได้ในการทำงานด้วยมากที่สุด "แบ็กเอนด์" parsers XML, lxml น่าจะเป็นหนึ่งในผู้สนับสนุน parsers crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
ffledgling

@ffledgling ฟังก์ชั่นบางอย่างของ BeautifulSoup ค่อนข้างเชื่องช้า
Lenar Hoyt

2

ฉันแนะนำให้ใช้ไลบรารีjustext :

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

การใช้: 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

ฉันจะใช้ EHP

https://github.com/iogf/ehp

นี่มันคือ:

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

เอาท์พุท:

Something here
Something else

5
กรุณาอธิบาย. สิ่งที่คุณจะใช้ EHP กับ BeautifulSoup หรือ lxml ยอดนิยม
ChaimG
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.