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