Розбір 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), ви б знали, що вона дає всі теги в приємному вкладеному вигляді, як дерево.

Я вважаю за краще вбудований модуль, але це, можливо, буде запитувати занадто багато.


Я пережив багато питань щодо переповнення стека та декількох блогів в Інтернеті, і більшість з них пропонують BeautifulSoup або lxml або HTMLParser, але деякі з них деталізують функціональність і просто закінчуються дискусією, щодо якої швидше / ефективніше.


2
як і всі інші відповідачі, я б рекомендував BeautifulSoup, тому що це дійсно добре для обробки зламаних файлів HTML.
Паскаль Росін

Відповіді:


195

Так що я можу попросити мене отримати вміст / текст у тезі div з class = 'контейнер', що міститься в тезі 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, за винятком того, що він має "хитрі" властивості, на зразок "body" буде посилатися на об'єкт BeautifulSoup (пам'ятайте, що це в основному вузол дерева) першого (і в цьому випадку , лише) body element кореневого елемента (у нашому випадку html)
Aadaam

18
Лише оновлення: станом на BeautifulSoup 4 зараз імпортна лініяfrom bs4 import BeautifulSoup
Бейлі Паркер

2
Загальна інформація: Якщо продуктивність є критичною, краще скористайтеся lxmlбібліотекою (див. Відповідь нижче). З cssselectвельми корисно як добре і продуктивністю часто від 10 до 100 разів краще , ніж у інших доступних бібліотек.
Ленар Хойт

Примітка: 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!
прогіаммер

41

Тут ви можете прочитати більше про різні парсери HTML в Python та їхню ефективність. Незважаючи на те, що стаття трохи датована, вона все ж дає хороший огляд.

Продуктивність синтаксичного аналізатора Python

Я б рекомендував 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
Я шукав щось, що деталізує функції / функціональність, а не продуктивність / ефективність. EDIT: Вибачте за передзрілу відповідь, це посилання насправді добре. Дякую.
вівторок

Перші види пунктів узагальнюють особливості та функції :)
Qiau

5
Якщо ви використовуєте BeautifulSoup4 (остання версія):from bs4 import BeautifulSoup
Франк Дернонкурт

29

Порівняно з іншими аналізаторами бібліотеки 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()
Гільєрмо Насіменто

Я аналізує величезні HTML-адреси для конкретних даних. Зробити це з BeautifulSoup зайняло 1.7секунду, але застосувавши lxml замість цього, прискорило це майже в *100рази швидше! Якщо піклуватися про продуктивність, lxml - найкращий варіант
Алекс-Богданов

9

Я рекомендую lxml для розбору HTML. Див. "Розбір HTML" (на сайті lxml).

З мого досвіду Beautiful Soup заплутався на деяких складних HTML. Я вважаю, що це тому, що Beautiful Soup - це не аналізатор, а дуже хороший аналізатор струн.


3
AIUI Beautiful Soup можна змусити працювати з більшістю "резервних" XML-аналізаторів, lxml, здається, є одним із підтримуваних парсерів crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
ffledgling

@ffledgling Деякі функції BeautifulSoup є досить млявими.
Ленар Хойт

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.