Синтаксический анализ HTML с помощью Python

Я ищу модуль синтаксического анализа HTML для 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 "Inspect element" (просмотр HTML) вы знаете, что она дает вам все теги в приятной вложенной манере, такой как дерево.

Я бы предпочел встроенный модуль, но это может быть слишком много.


Я прошел через много вопросов о переполнении стека и несколько блогов в интернете, и большинство из них предлагают BeautifulSoup или lxml или HTMLParser, но немногие из них подробно описывают функциональность и просто заканчиваются дискуссией о том, какой из них быстрее/больше эффективно.

7 ответов


Так что я могу в основном попросить его получить мне содержимое / текст в теге 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 работает. Посмотрите на его официальная документация.


Я думаю, что вы ищете это 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. Например:

the element selector is 'div#mw-head.noprint'

проверенный селектор элемента " div#mw-head.noprint'. Поэтому в pyquery вам просто нужно передать этот селектор:

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

здесь вы можете узнать больше о различных парсерах 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

по сравнению с другими библиотеками парсер 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


рекомендую библиотека lxml для синтаксического анализа HTML. См. "синтаксический анализ HTML" (на сайте lxml).

по моему опыту, красивый суп испортился на каком-то сложном HTML. Я считаю, что это потому, что красивый суп не парсер, а очень хороший анализатор строк.


Я рекомендую использовать 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)

Я бы использовал 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