Парсер BeautifulSoup 3.1 слишком легко ломается

У меня возникли проблемы с разбором некоторых хитрых HTML-кодов с помощью BeautifulSoup. Оказывается, HTMLParser, используемый в более новых версиях, менее устойчив, чем SGMLParser, использовавшийся ранее.


Есть ли у BeautifulSoup какой-то режим отладки? Я пытаюсь понять, как остановить его на каком-то неприятном HTML, который я загружаю с раздражительного веб-сайта:

<HTML>
    <HEAD>
        <TITLE>Title</TITLE>
        <HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
    </HEAD>
    <BODY>
        ...
        ...
    </BODY>
</HTML>

BeautifulSoup сдается после тега <HTTP-EQUIV...>

In [1]: print BeautifulSoup(c).prettify()
<html>
 <head>
  <title>
   Title
  </title>
 </head>
</html>

Проблема явно заключается в теге HTTP-EQUIV, который на самом деле представляет собой очень искаженный тег <META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">. Очевидно, мне нужно указать это как самозакрывающееся, но независимо от того, что я указываю, я не могу это исправить:

In [2]: print BeautifulSoup(c,selfClosingTags=['http-equiv',
                            'http-equiv="pragma"']).prettify()
<html>
 <head>
  <title>
   Title
  </title>
 </head>
</html>

Есть ли подробный режим отладки, в котором BeautifulSoup сообщит мне, что он делает, чтобы я мог понять, что в этом случае он обрабатывает как имя тега?


person Mat    schedule 19.01.2009    source источник


Ответы (3)


Ваша проблема должна быть чем-то другим; Он отлично работает для меня:

In [1]: import BeautifulSoup

In [2]: c = """<HTML>
   ...:     <HEAD>
   ...:         <TITLE>Title</TITLE>
   ...:         <HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
   ...:     </HEAD>
   ...:     <BODY>
   ...:         ...
   ...:         ...
   ...:     </BODY>
   ...: </HTML>
   ...: """

In [3]: print BeautifulSoup.BeautifulSoup(c).prettify()
<html>
 <head>
  <title>
   Title
  </title>
  <http-equiv>
  </http-equiv>
 </head>
 <body>
  ...
        ...
 </body>
</html>


In [4]: 

Это Python 2.5.2 с BeautifulSoup 3.0.7a — может быть, в старых/новых версиях по-другому? Это именно тот суп, с которым BeautifulSoup так прекрасно справляется, поэтому я сомневаюсь, что он был изменен в какой-то момент… Есть ли что-то еще в структуре, что вы не упомянули в задаче?

person ShreevatsaR    schedule 19.01.2009
comment
У меня есть Python 2.5.1 и BeautifulSoup 3.1.0.1. Первоначальная сломанная структура была другой, но проблема также возникает с упрощенной структурой в вопросе. Я только что запустил код в вашем примере и столкнулся с той же проблемой, что и раньше, ничего после ‹/title›. Теперь я действительно смущен! - person Mat; 20.01.2009
comment
Одна из возможностей заключается в том, что BeautifulSoup что-то сломал при обновлении ... вы пытались скопировать текст именно из вашего вопроса здесь? - person ShreevatsaR; 20.01.2009
comment
crummy.com/software/BeautifulSoup/CHANGELOG.html BeautifulSoup 3.1 основан на HTMLParser, а не SGMLParser (поскольку последний отсутствует в Python 3.0), что может быть здесь проблемой. Печально... - person ShreevatsaR; 20.01.2009
comment
Да, я пытался с точным текстом в вопросе, и я только что скопировал и вставил еще раз, чтобы быть уверенным. Звучит как боль, что парсер изменился. Возможно, мне следует вставить быстрое регулярное выражение, чтобы избавиться от испорченного HTML. Не похоже, что я собираюсь встретить что-то подобное в другом месте. - person Mat; 20.01.2009

Возникли проблемы с Beautiful Soup 3.1.0? рекомендует использовать парсер html5lib как один из обходных путей.

#!/usr/bin/env python
from html5lib import HTMLParser, treebuilders

parser = HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))

c = """<HTML>
    <HEAD>
        <TITLE>Title</TITLE>
        <HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
    </HEAD>
    <BODY>
        ...
        ...
    </BODY>
</HTML>"""

soup = parser.parse(c)
print soup.prettify()

Выход:

<html>
 <head>
  <title>
   Title
  </title>
 </head>
 <body>
  <http-equiv="pragma" content="NO-CACHE">
   ...
        ...
  </http-equiv="pragma">
 </body>
</html>

Вывод показывает, что html5lib не устранил проблему в этом случае.

person jfs    schedule 12.03.2009

Попробуйте lxml (и его html-модуль). Несмотря на свое название, он также предназначен для анализа и очистки HTML. Это намного, намного быстрее, чем BeautifulSoup, и даже обрабатывает «сломанный» HTML лучше, чем BeautifulSoup. Он также имеет API совместимости для BeautifulSoup, если вы не хотите изучать API lxml.

Ян Бликинг соглашается.

Больше нет причин использовать BeautifulSoup, если только вы не используете Google App Engine или что-то еще, где не разрешено ничего, кроме Python.

person aehlke    schedule 03.08.2009