Как сделать универсальный фид-парсер только парсом фидов?


Я пытаюсь получить контент из внешних каналов на моем веб-сайте Django с помощью универсального анализатора каналов. Я хочу иметь некоторую обработку ошибок пользователя, например, если пользователь предоставляет URL, который не является каналом. Когда я попробовал, как feedparser реагирует на ошибочный ввод, я был удивлен, увидев, что feedparser вообще не выдает никаких исключений. Например, на HTML-контенте он пытается проанализировать некоторую информацию из HTML-кода, а на несуществующих доменах он возвращает в основном пустой словарь:

{'bozo': 1,
'bozo_exception': URLError(gaierror(-2, 'Name or service not known'),),
'encoding': 'utf-8',
'entries': [],
'feed': {},
'version': None}

Другие ошибочные входные данные проявляются в значениях status_code или namespaces возвращаемого словаря.

Итак, каков наилучший подход, чтобы иметь нормальную проверку ошибок, не прибегая к бесконечному каскаду if .. elif .. elif ...?

1 3

1 ответ:

Согласно документации feedparser, в разделе обнаружение Бозо :

Универсальный анализатор каналов может анализировать каналы независимо от того, являются ли они хорошо сформированными XML или нет. Однако, поскольку некоторые приложения могут отклонять или предупреждать пользователей о неполной форме каналов, универсальный анализатор каналов устанавливает бит bozo, когда он обнаруживает, что канал не является хорошо сформированным.

(на мой взгляд, это не очень хорошая практика, чтобы поймать все исключения и вернуть их в другой форме, но это именно так это и работает, поскольку "приложения могут просто предупреждать о не очень хорошо сформированных каналах".)

Таким образом, после попытки проанализировать канал по любому URL, вы можете проверить наличие "Бозо-бита" и повторно вызвать соответствующее исключение:

f = feedparser.parse('http://example.com')
if f.bozo:
    raise f.bozo_exception

Вы можете обрабатывать исключение в соответствии с типом и сообщением или путем утверждения других атрибутов объекта, возвращаемых feedparser.parse (например: f.feed должен быть непустым, f.status должен равняться 200, f.entries должен быть непустым, f.version должен быть допустимым форматом канала версия и т. д.), все, что кажется наиболее разумным для вашего приложения.