Python html синтаксический анализ, который фактически работает
Я пытаюсь разобрать некоторый html в Python. Были некоторые методы, которые на самом деле работали до этого... но в настоящее время я ничего не могу использовать без обходных решений.
- У beautifulsoup есть проблемы после выхода SGMLParser.
- html5lib не может разобрать половину того, что "там"
- lxml пытается быть "слишком правильным" для типичного html (атрибуты и теги не могут содержать неизвестные пространства имен или исключение, что означает, что почти никакая страница с подключением Facebook не может быть проанализирована).
Какие еще варианты существуют в наши дни? (если они поддерживают xpath, это было бы здорово)
Ответы
Ответ 1
Убедитесь, что вы используете модуль html
при анализе HTML с помощью lxml
:
>>> from lxml import html
>>> doc = """<html>
... <head>
... <title> Meh
... </head>
... <body>
... Look at this interesting use of <p>
... rather than using <br /> tags as line breaks <p>
... </body>"""
>>> html.document_fromstring(doc)
<Element html at ...>
Все ошибки и исключения будут таять, вы останетесь с удивительно быстрым парсером, который часто имеет дело с супом HTML лучше, чем BeautifulSoup.
Ответ 2
Я использовал pyparsing для нескольких проектов соскабливания HTML-страниц. Это своего рода промежуточная точка между BeautifulSoup и полными HTML-парсерами на одном конце, а также слишком низкий уровень регулярных выражений (таким образом, это безумие).
С помощью pyparsing вы часто можете получить хорошие результаты HTML-поиска, идентифицируя конкретное подмножество страницы или данных, которые вы пытаетесь извлечь. Такой подход позволяет избежать проблем, связанных с попыткой разобрать все на странице, так как некоторые проблемные HTML за пределами интересующего вас региона могут отбросить полный анализатор HTML.
Хотя это звучит просто как прославленный подход с регулярным выражением, pyparsing предлагает встроенные функции для работы с текстом HTML или XML. Pyparsing избегает многих подводных камней, которые расстраивают решения на основе регулярных выражений:
- принимает пробелы без мусора '\ s *' по всему вашему выражению
- обрабатывает неожиданные атрибуты в тегах
- обрабатывает атрибуты в любом порядке
- обрабатывает верхний/нижний регистр в тегах
- обрабатывает имена атрибутов с пространствами имен
- обрабатывает значения атрибутов в двойных кавычках, одинарные кавычки или без кавычек
- обрабатывает пустые теги (те формы
<blah />
)
- возвращает данные синтаксического тега с доступом объекта к атрибутам тега
Вот простой пример из википики pyparsing, которая получает теги <a href=xxx>
с веб-страницы:
from pyparsing import makeHTMLTags, SkipTo
# read HTML from a web page
page = urllib.urlopen( "http://www.yahoo.com" )
htmlText = page.read()
page.close()
# define pyparsing expression to search for within HTML
anchorStart,anchorEnd = makeHTMLTags("a")
anchor = anchorStart + SkipTo(anchorEnd).setResultsName("body") + anchorEnd
for tokens,start,end in anchor.scanString(htmlText):
print tokens.body,'->',tokens.href
Это вытащит теги <a>
, даже если есть другие части страницы, содержащие проблемный HTML. В википапии pyparsing есть другие примеры HTML:
Pyparsing не является полным надежным решением этой проблемы, но, подвергая процесс разбора вам, вы можете лучше контролировать, какие фрагменты HTML-кода вам особенно интересны, обрабатывать их и пропускать остальные.
Ответ 3
html5lib не может разобрать половину того, что "там"
Это звучит крайне неправдоподобно. html5lib использует точно такой же алгоритм, который также реализован в последних версиях Firefox, Safari и Chrome. Если бы этот алгоритм сломал половину сети, я думаю, мы бы услышали. Если у вас есть определенные проблемы с этим, делайте файлы ошибок.
Ответ 4
Если вы очищаете контент, отличный способ обойти раздражающие детали - это sitescraper. Он использует машинное обучение для определения того, какой контент нужно получить для вас.
На главной странице:
>>> from sitescraper import sitescraper
>>> ss = sitescraper()
>>> url = 'http://www.amazon.com/s/ref=nb_ss_gw?url=search-alias%3Daps&field-keywords=python&x=0&y=0'
>>> data = ["Amazon.com: python",
["Learning Python, 3rd Edition",
"Programming in Python 3: A Complete Introduction to the Python Language (Developer Library)",
"Python in a Nutshell, Second Edition (In a Nutshell (O'Reilly))"]]
>>> ss.add(url, data)
>>> # we can add multiple example cases, but this is a simple example so 1 will do (I generally use 3)
>>> # ss.add(url2, data2)
>>> ss.scrape('http://www.amazon.com/s/ref=nb_ss_gw?url=search-alias%3Daps&field- keywords=linux&x=0&y=0')
["Amazon.com: linux", ["A Practical Guide to Linux(R) Commands, Editors, and Shell Programming",
"Linux Pocket Guide",
"Linux in a Nutshell (In a Nutshell (O'Reilly))",
'Practical Guide to Ubuntu Linux (Versions 8.10 and 8.04), A (2nd Edition)',
'Linux Bible, 2008 Edition: Boot up to Ubuntu, Fedora, KNOPPIX, Debian, openSUSE, and 11 Other Distributions']]
Ответ 5
Я думаю, проблема в том, что большинство HTML плохо сформировано. XHTML попытался это исправить, но он никогда не попадал на достаточное количество - особенно, поскольку большинство браузеров "интеллектуальных обходных решений" для плохо сформированного кода.
Еще несколько лет назад я попытался разобрать HTML для примитивного приложения для пауков и нашел проблемы слишком сложными. Я подозреваю, что на ваших карточках можно писать свои собственные, хотя мы не можем быть единственными людьми с этой проблемой!