Разбор HTML Python, который на самом деле работает - PullRequest
15 голосов
/ 06 ноября 2010

Я пытаюсь разобрать HTML в Python. Существовали некоторые методы, которые действительно работали раньше ... но в настоящее время нет ничего, что я мог бы на самом деле использовать без обходных путей.

  • Beautifulsoup имеет проблемы после того, как SGMLParser ушел
  • html5lib не может разобрать половину того, что "там"
  • lxml пытается быть «слишком корректным» для типичного html (атрибуты и теги не могут содержать неизвестные пространства имен, или выдается исключение, что означает, что почти невозможно проанализировать страницу с подключением Facebook)

Какие еще варианты есть в эти дни? (если они поддерживают xpath, это было бы здорово)

Ответы [ 5 ]

20 голосов
/ 06 ноября 2010

Убедитесь, что вы используете модуль 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.

10 голосов
/ 06 ноября 2010

Я использовал pyparsing для ряда проектов очистки страниц HTML.Это своего рода золотая середина между BeautifulSoup и парсерами полного HTML на одном конце, и слишком низкоуровневый подход к регулярным выражениям (таким образом - безумие).

С помощью pyparsing вы часто можете получитьхорошие результаты анализа HTML-данных путем определения конкретного подмножества страницы или данных, которые вы пытаетесь извлечь.Этот подход позволяет избежать попыток разбора всего на странице, поскольку некоторые проблематичные HTML-коды за пределами области вашего интереса могут вызвать сложный анализатор HTML.

Хотя это звучит как простоПодход, основанный на регулярных выражениях, pyparsing предлагает встроенные функции для работы с HTML- или XML-тегами.Pyparsing позволяет избежать многих ловушек, которые расстраивают решения на основе регулярных выражений:

  • принимает пробелы без символа «\ s *» по всему выражению
  • обрабатывает неожиданные атрибуты внутри тегов
  • обрабатывает атрибуты в любом порядке
  • обрабатывает верхний / нижний регистр в тегах
  • обрабатывает имена атрибутов с помощью пространств имен
  • обрабатывает значения атрибутов в двойных кавычках, одинарных кавычках или нет кавычки
  • обрабатывает пустые теги (теги вида <blah />)
  • возвращает проанализированные данные тега с доступом к атрибутам объекта к атрибутам тега

Вот простой пример из pyparsing wiki, который получает <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 вам интересны, обрабатывать их и пропускать остальные.

5 голосов
/ 06 ноября 2010

html5lib не может разобрать половину того, что "там"

Это звучит невероятно неправдоподобно.html5lib использует точно такой же алгоритм, который также реализован в последних версиях Firefox, Safari и Chrome.Если бы этот алгоритм сломал половину сети, я думаю, мы бы услышали.Если у вас есть определенные проблемы с этим, делайте ошибки файла.

4 голосов
/ 06 ноября 2010

Если вы просматриваете содержимое, отличный способ обойти раздражающие детали - пакет 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's 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']]
1 голос
/ 06 ноября 2010

Я думаю, что проблема в том, что большинство HTML-файлов плохо сформировано.XHTML пытался это исправить, но он так и не завоевал популярность, особенно потому, что большинство браузеров делают «интеллектуальные обходные пути» для плохо сформированного кода.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...