Эффективное использование HTMLParser в Python - PullRequest
4 голосов
/ 15 ноября 2010

В ответ на Регулярное выражение Python Я попытался реализовать анализатор HTML, используя HTMLParser:

import HTMLParser

class ExtractHeadings(HTMLParser.HTMLParser):

  def __init__(self):
    HTMLParser.HTMLParser.__init__(self)
    self.text = None
    self.headings = []

  def is_relevant(self, tagname):
    return tagname == 'h1' or tagname == 'h2'

  def handle_starttag(self, tag, attrs):
    if self.is_relevant(tag):
      self.in_heading = True
      self.text = ''

  def handle_endtag(self, tag):
    if self.is_relevant(tag):
      self.headings += [self.text]
      self.text = None

  def handle_data(self, data):
    if self.text != None:
      self.text += data

  def handle_charref(self, name):
    if self.text != None:
      if name[0] == 'x':
        self.text += chr(int(name[1:], 16))
      else:
        self.text += chr(int(name))

  def handle_entityref(self, name):
    if self.text != None:
      print 'TODO: entity %s' % name

def extract_headings(text):
  parser = ExtractHeadings()
  parser.feed(text)
  return parser.headings

print extract_headings('abdk3<h1>The content we need</h1>aaaaabbb<h2>The content we need2</h2>')
print extract_headings('before<h1>&#72;e&#x6c;&#108;o</h1>after')

Делая это, я задавался вопросом, является ли API этого модуля плохим или я не заметил некоторых важных вещей. Мои вопросы:

  • Почему моя реализация handle_charref должна быть такой сложной? Я ожидал бы, что хороший API передает кодовую точку в качестве параметра, а не x6c или 72 в виде строки.
  • Почему стандартная реализация handle_charref не вызывает handle_data с соответствующей строкой?
  • Почему нет реализации утилиты handle_entityref, которую я мог бы просто вызвать? Он может иметь имя handle_entityref_HTML4 и искать сущности, определенные в HTML 4, а затем вызывать handle_data для них.

Если бы этот API был предоставлен, написание пользовательских HTML-парсеров было бы намного проще. Так где же мое недоразумение?

Ответы [ 2 ]

1 голос
/ 15 ноября 2010

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

Однако, похоже, мы можем написать довольно простой обработчик сущностей что-то вроде:

import htmlentitydefs
def entity2char(x):
    if x.startswith('&#x'):
        # convert from hexadecimal
        return chr(int(x[3:-1], 16))
    elif x.startswith('&#'):
        # convert from decimal
        return chr(int(x[2:-1]))
    elif x[1:-1] in htmlentitydefs.entitydefs:
        return htmlentitydefs.entitydefs[x[1:-1]]
    else:
        return x

... хотя мы должны обернутьдля дальнейшей проверки правильности ввода и включения целочисленных преобразований в код обработки исключений.

Но это должно обрабатывать самый минимум примерно в 10 строках кода.Добавление обработки исключений, возможно, удвоит количество строк.

0 голосов
/ 15 ноября 2010

Вам нужно реализовать свой собственный парсер или вы уже можете создать его? Посмотрите на красивый суп .

...