Python Feedparser: как я могу проверить новые данные RSS?

Я использую библиотеку python feedparser для непрерывного вывода RSS-данных из фида. Я написал свой код python таким образом, что могу запросить один экземпляр данных RSS. Здесь мой код:

import feedparser

rssPR = feedparser.parse('http://www.prnewswire.co.uk/rss/consumer-technology/wireless-      communications-news.rss')
rssDataList = []

for index, item in enumerate(rssPR.entries):
    rssDataList.append([item.published.encode('utf-8'), item.title.encode('utf-8')])

print rssDataList[0]  #for debugging purposes
print rssPR.modified #for testing purposes
  • Что я могу добавить в свой код, чтобы он проверял только новые данные RSS тогда и только тогда, когда RSS был изменен?

  • Скажем, у меня есть список из 10 элементов RSS, а RSS-канал обновлен двумя новыми элементами RSS. Как я могу добавить только эти 2 элемента в созданный rssDataList? Я не хочу добавлять одни и те же RSS файлы в мою базу данных.

Ответ 1

Относительно загрузки только в том случае, если/при изменении фида вы можете использовать HTTP-заголовок etag и Last-Modified.

>>> feed.etag
'"6c132-941-ad7e3080"'
>>> feed.modified
'Fri, 11 Jun 2012 23:00:34 GMT'

Вы можете указать их в своем обращении к feedparser.parse. Если они все те же (без изменений), запрос будет иметь код состояния 304 (не изменен).

Это сводится к следующему примеру:

import feedparser
url = 'http://feedparser.org/docs/examples/atom10.xml'

# first request
feed = feedparser.parse(url)

# store the etag and modified
last_etag = feed.etag
last_modified = feed.modified

# check if new version exists
feed_update = feedparser.parse(url, etag=last_etag, modified=last_modified)

if feed_update.status == 304:
    # no changes

Примечания: Вам нужно проверить, существуют ли feed.etag и feed.modified.

Источник: Документация Feedparser о http и etag

Ответ 2

Это вопрос сборки или покупки. Если вы покупаете, отметьте Superfeedr (который я создал!): он сделает это для вас и отправит вам новые записи (нормализованные в JSON или Atom) с помощью веб-кнопок.

Если вы строите, первое, что нужно сделать, это проверить спецификации RSS и Atom. У обоих есть элемент для идентификации уникальных записей/элементов: RSS имеет <guid>, в то время как ATOM имеет <id>. Таким образом, при опросе фида вам просто нужно отслеживать их, чтобы идентифицировать новые и старые записи. Около 10% кормов там не включают такой элемент... что означает, что вам придется использовать что-то еще, будь то название, ссылка или хеш, но это, вероятно, будет менее совершенным решением с ложными срабатываниями и ложными отрицаниями:( Он также рекомендовал проверить элемент <updated> в ATOM для определения изменений в фиде.

Теперь это не поможет с вашим первым вопросом: вам, вероятно, придется периодически проверять фид, не зная, есть ли у него новый элемент или нет. Он рекомендовал использовать доступные HTTP-методы, такие как заголовки Etag или Last-Modified, чтобы избежать переноса устаревших данных. Вероятность вашей частоты опроса, вероятно, должна основываться на средней частоте обновления фида, и насколько важно, чтобы вы своевременно регистрировали эти записи.

Наконец, единственный способ узнать, что фид был обновлен, - это реализовать открытый протокол PubSubHubbub. В принципе, это позволит вам зарегистрировать webhook, чтобы узнать, когда фид был обновлен. Его принятие зависит от домена, но для блогов он достигает 50% на данный момент. Superfeedr может выступать в качестве "стандартного" концентратора, который работает для любого канала, используя протокол PubSubHubbub!

Ответ 3

Ну, есть много разных способов решить эту проблему. Одним из самых простых ИМО было бы создание уникального "хэша" самой последней записи. Например:

import hashlib
import feedparser

rssPR = feedparser.parse('http://www.prnewswire.co.uk/rss/consumer-technology/wireless-communications-news.rss')
rssDataList = []

# Generate MD5 hash of the most current item title and link elements.
lasthash = hashlib.md5(rssPR.entries[0].link + rssPR.entries[0].title).hexdigest()

for index, item in enumerate(rssPR.entries):
    rssDataList.append([item.published.encode('utf-8'), item.title.encode('utf-8')])

print rssPR.modified # Thu, 06 Mar 2014 00:13:50 GMT
print lasthash # 4167402f1ba2629fcc71003121aa1d25

Тогда, если вы сделаете что-то вроде этого:

rssCheck = feedparser.parse('http://www.prnewswire.co.uk/rss/consumer-technology/wireless-communications-news.rss')
thishash = hashlib.md5(rssCheck.entries[0].link + rssCheck.entries[0].title).hexdigest()

lasthash == thishash
>> True # up to date

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