Разбор 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, но лишь немногие из них подробно описывают функциональность и просто заканчиваются дискуссией о том, какой из них быстрее / эффективнее.

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

Ответы:

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. Посмотрите на его официальную документацию .

Aadaam
источник
2
Что именно является объектом parsed_html?
окопался
1
parsed_html - это объект BeautifulSoup, думайте о нем как о DOMElement или DOMDocument, за исключением того, что он имеет «хитрые» свойства, например, «body» будет ссылаться на объект BeautifulSoup (помните, это в основном узел дерева) первого (и в этом случае , только) элемент body корневого элемента (в нашем случае, html)
Aadaam
18
Просто обновление: начиная с BeautifulSoup 4, линия импорта теперьfrom bs4 import BeautifulSoup
Bailey Parker
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')
YusuMishi
источник
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
Qiau
источник
2
Я искал что-то, что детализирует функции / функциональность, а не производительность / эффективность. РЕДАКТИРОВАТЬ: Извините за преждевременный ответ, эта ссылка на самом деле хорошо. Спасибо.
окопался
Первые точки списка видов суммируют функции и функции :)
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 use 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