2014-12-23 4 views
2

Однако я нашел много ответов здесь, к сожалению, они не работают для меня.Python 3 XML parser unkown entity error

У меня Ubuntu x64, python 3.4.2.

Я разборе веб-страницы с HTML сущностей, как   среди прочего:

import xml.etree.ElementTree as ET 
page = 'some string I get from requests.get' 
parser = ET.XMLParser() 
parser.parser.UseForeignDTD(True) 
tree = ET.fromstring(page, parser=parser) 

Много ответов содержат этот код, чтобы предотвратить ошибки, как unknown entity &nbps;. В то время как я скомпилировать этот код он выдает ошибку:

AttributeError: 'xml.etree.ElementTree.XMLParser' object has no attribute 'parser'

или

AttributeError: 'xml.etree.ElementTree.XMLParser' object has no attribute '_parser'

(depdends на то, что член parser объекта я написал в 4-й строке в коде выше). Магия, когда я пытаюсь идти к этому коду из PyCharm IDE он показывает мне, что этот член существует и успешно создает в конструкторе класса:

# underscored names are provided for compatibility only 
self.parser = self._parser = parser 
self.target = self._target = target 

Мои вопросы:

  1. Почему этот Работа ?
  2. Можно ли не добавлять каждый объект вручную, чтобы предотвратить ошибки синтаксического анализа?

ответ

1

Сегодня я столкнулся с этой проблемой, хотя я нахожусь на Python 2.7.3. Насколько я вижу, это работает в первый раз, когда вы его пытаетесь, но в какой-то момент парсер действительно потеряет свой атрибут _parser. Если вы можете исследовать объект в том месте, в котором оно выбрасывает это исключение, а не при создании, то вы увидите, что он не лжет.

Досадно, что я не мог понять, как это происходит. Я попытался обезьяны повязкой на XMLParser.feed() метод, который является то, что вызывает это исключение:

def feed(self, data): 
    try: 
     self._parser.Parse(data, 0) 
    except self._error, v: 
     self._raiseerror(v) 

для удаления _, так как атрибут parser все же остается, и должна быть такой же, как _parser. Но потом я начал получать ошибки, которые предполагали, что синтаксический анализатор все еще переносил состояние из предыдущего вызова fromstring.

Вместо того, что в конечном счете работал для меня было просто воссоздать XMLParser объект каждый раз, когда я нуждался в нем, т.е.

class DecodeEntities: 
    def __getitem__(self, key): 
     if key in name2codepoint: 
      return unichr(name2codepoint[key]) 
     else: 
      # Note that this removes unrecognised entities 
      return '' 

class Parse: 
    def from_unicode(self, unic): 
     # We also want the parser to understand HTMLX entities. 
     # Note that this has to be created every time - reusing a 
     # parser appears not to be possible. 
     parser = ElementTree.XMLParser() 
     parser.parser.UseForeignDTD(True) 
     parser.entity = DecodeEntities() 

     ret = ElementTree.fromstring(unic, parser=parser)