Сохранение данных Google Reader

от автора

Чем ближе дата закрытия Google Reader тем более насущным становится вопрос не только переноса подписок в аналогичный сервис, но и сохранения всех текущих записей.

Найденные решения, в том числе и на хабре(здесь и здесь), не подошли в основном по двум причинам: нет возможности сохранения в БД и медленная скорость работы. Пришлось собрать свой велосипед — grbackup, который

grbackup -e fake@gmail.com -p password -ba -o mongodb://localhost:27017 -w 20 

за 20 минут сохранил 328250 записей из 102 подписок в локальную БД MongoDB.

Основные возможности:

  • сохранение всех записей, которые можно получить при помощи Google Reader API
  • сохранение записей в различные хранилища
  • использование формата идентичного тому, что отдает Google Reader через API
  • параллельное получение/сохранение записей
  • расширяемость: возможность добавить новый вид хранилища

Доступные виды хранилищ определяются расширениями(плагинами) и задаются при помощи опции (-o, —output) вида type:uri.
На момент написания статьи доступны следующие расширения:

  • simple: вывод в терминал (используется только в режиме просмотра)
  • json: запись в json-файл (json:/path/to/file.json)
  • mongodb: запись в MongoDB (mongodb://[username:password@]hostN[:portN]]][/[db][?opts]])
  • redis: запись в Redis (redis://username:password@host[:port]/dbindex)

Работоспособность проверена на Ubuntu(64) и Win7(64).
Книгу предложений и замечаний можно найти здесь.
Ниже находится подробное описание утилиты.

Установка

pip install grbackup 

или

easy_install grbackup 

или

pip install git+git://github.com/wistful/grbackup.git 

Опций командной строки

Авторизация

  • -e, —email: почтовый адрес используемый для входа в Google Reader
  • -p, —password: пароль

grbackup поддерживает два действия:

  • просмотр:-l, —list
  • сохранение: -b, —backup

Действие можно выполнить над одним из четырех типов данных:

  • подписки; -s, —subscriptions
  • записи: -t, —topics
  • отмеченные записи: -x, —starred
  • все предыдущие вместе взятые: -a, —all

Дополнительные опции:

  • -w, —workers: максимальное количество одновременно обрабатываемых подписок (по умолчанию 1)
  • -o, —output: URI показывающий куда сохранять записи
  • -n, —count: количество записей получаемых от Google Reader за один запрос (по умолчанию 200). Слишком большое число может привести к получению данных более мелкими порциями (ох уж этот google).

Все опции, а также описание плагинов можно просмотреть используя опцию -h, —help:

grbackup -h 

вывод предыдущей команды

Usage: grbackup [options] [args]  Examples:     list subscriptions: grbackup -e email@gmail.com -p password -ls    list topics: grbackup -e email@gmail.com -p password -lt http://feed.com    list starred: grbackup -e email@gmail.com -p password -lx    list all items: grbackup -e email@gmail.com -p password -la     backup subscriptions: grbackup -e email@gmail.com -p password -bs -o json:/tmp/subscriptions.json    backup topics: grbackup -e email@gmail.com -p password -bt http://myfeed.com -o json:/tmp/myfeed.json    backup starred into MongoDB: grbackup -e email@gmail.com -p password -bx -o mongodb://localhost:27017    backup all items into Redis: grbackup -e email@gmail.com -p password -ba -o redis://localhost:6379/3  Available plugins:    mongodb:  save items into MongoDB             output scheme:   mongodb://[username:password@]hostN[:portN]]][/[db][?opts]]             output examples: mongodb://localhost:27017                              mongodb://user:pwd@localhost,localhost:27018/?replicaSet=grbackup                json:     save items into file             output scheme:   json:/path/to/file.json             output examples: json:/home/grbackup/grbackup.json                              json:/tmp/grbackup/grbackup.json                redis:    save items into Redis             output scheme:   redis://username:password@host[:port]/dbindex             output examples: redis://localhost:6379/3                              redis://user:password@localhost:6379/0               Options:   Auth Options:     -e EMAIL, --email=EMAIL                         gmail account     -p PWD, --password=PWD                         account password    Command Options:     -b, --backup        backup items     -l, --list          list items    Scope Options:     -a, --all           processing all items     -s, --subscriptions                         processing subscriptions only     -t, --topics        processing topics only     -x, --starred       processing starred topics only    MongoDB Options:     --mongodb-db=MONGODB_DB                         the name of the database[default: greader]     --mongodb-scol=MONGODB_SUBSCRIPTIONS                         collection name for subscriptions[default:                         subscriptions]     --mongodb-tcol=MONGODB_TOPICS                         collection name for topics[default: topics]     --mongodb-tstar=MONGODB_STARRED                         collection name for starred items[default: starred]     --mongodb-w=MONGODB_W                         <int> Write operations will block until they have been                         replicated to the specified number [default: 1]     --mongodb-j         block until write operations have been committed to                         the journal [default: False]    Redis Options:     --redis-scol-prefix=REDIS_SUBS                         subscriptions key prefix[default: subscription]     --redis-tcol-prefix=REDIS_TOPICS                         topics key prefix[default: topic]     --redis-xcol-prefix=REDIS_STARRED                         starred key prefix[default: starred]    Other Options:     -w WORKERS, --workers=WORKERS                         number of workers [default: 1]     -o OUTPUT, --output=OUTPUT                         output uri     -n COUNT, --count=COUNT                         the number of topics that can be read at once                         [default: 200]     -c CODING, --coding=CODING                         output coding [default: utf8]     -v, --verbose       verbose output     -h, --help   

Использование

список подписок:

grbackup -e email@gmail.com -p password -ls 

список записей конкретной подписки:

 grbackup -e email@gmail.com -p password -lt http://habrahabr.ru/rss/hub/python/ 

список всех отмеченных записей:

grbackup -e email@gmail.com -p password -lx 

список всех записей:

grbackup -e email@gmail.com -p password -la 

сохранение подписок в json-файл:

 grbackup -e email@gmail.com -p password -bs -o json:/tmp/subscriptions.json 

сохранение всех записей конкретной подписки в json-файл:

grbackup -e email@gmail.com -p password -bt http://habrahabr.ru/rss/hub/python/ -o json:/tmp/python.json 

сохранение всех отмеченных записей в MongoDB:

grbackup -e email@gmail.com -p password -bx -o mongodb://localhost:27017 

сохранение всех записей в Redis с использованием 20 потоков:

grbackup -e email@gmail.com -p password -ba -o redis://localhost:6379/3 -w 20 

Плагины

JSON

Общий формат URI: json:/path/to/file.json
Поддержка многопоточности: да
Пример использования:

grbackup -e email@gmail.com -p password -ba -o json:/home/grbackup/grbackup.json 

Записи сохраняются в отдельный файл в виде списка объектов.
Существует три типа объектов:

  • подписки: {«type»: «subscription», «value»: subscription}
  • отмеченные записи: {«type»: «starred», «value»: record}
  • обычная запись: {«type»: «topic», «subscription»: subscription_url, «value»: record}
MongoDB

Общий формат URI: mongodb://[username:password@]hostN[:portN]]][/[db][?opts]]
Поддержка многопоточности: да
Пример использования:

grbackup -e email@gmail.com -p password -ba -o mongodb://localhost:27017 -w 20 

Записи раскладываются по трем коллекциям: subscriptions, topics, starred.
Имена коллекций можно изменять.

Redis

Общий формат URI: redis://username:password@host[:port]/dbindex
Поддержка многопоточности: да
Пример использования:

grbackup -e email@gmail.com -p password -ba -o redis://user:password@localhost:6379/0 -w 20 

Для хранения записей используется тип данных Hashes.
Ключи могут быть трех типов: «subscription:record_id», «starred:record_id», «topic:record_id», где record_id — уникальный идентификатор записи.
Префиксы ключей можно изменять.

Свой плагин

Модуль должен находится в пакете grb_plugins, имя модуля не имеет значения.
Структура модуля:

  • plugin_type — строковый тип, содержит имя плагина
  • support_threads — логический тип, указывает на возможность использования нескольких потоков
  • descriptions — строковый тип, содержит описание плагина
  • add_option_group — функция добавляющая дополнительные опции комадной строки
  • writer — контекстный менеджер возвращающий объект с методами:
    • put_subscription(subscription) — вызывается при сохранение подписки, subscription — словарь
    • put_starred(topic) — вызывается при сохранении отмеченной записи, topic — словарь
    • put_topic(self, subscription_url, topic) — вызывается при сохранении записи (опция ‘-t’, ‘—topics‘),
      topic — словарь, subscription_url — строковый адрес подписки
    • put_all(subscription, topic) — вызывается при сохранении записи с использованием опции ‘-a’, ‘—all’,
      subscription и topic — словари

Пример плагина использующего logging для сохранения записей в файл

#!/usr/bin/env python # coding=utf-8 from optparse import OptionGroup import logging  plugin_type = "myplugin" support_threads = True description = """save items using logging output scheme:   myplugin:/path/to/logfile.log output examples: myplugin:/tmp/storage.log """  def add_option_group(parser):     # Plugin Options     myplugin_group = OptionGroup(parser, "myplugin Options")     myplugin_group.add_option("--myplugin-format",                               dest="format",                               type="str",                               default="%(asctime)s %(message)s",                               help="record format"                               "[default: %default]")     myplugin_group.add_option("--myplugin-datefmt",                               dest="datefmt",                               type="str",                               default="%m/%d/%Y %I:%M:%S %p",                               help="date format"                               "[default: %default]")     parser.add_option_group(myplugin_group)   class WriteMyPlugin(object):      def __init__(self, logger):         self.logger = logger      def put_subscription(self, subscription):         subscription_url = subscription['id'][5:]         self.logger.warning("write subscription: %s", subscription_url)      def put_all(self, subscription, topic):         subscription_url = subscription['id'][5:]         self.put_subscription(subscription)         self.put_topic(subscription_url, topic)      def put_starred(self, topic):         self.logger.warning("write starred: %s", topic.get('title', ''))      def put_topic(self, subscription_url, topic):         self.logger.warning("write topic: %s %s",                             subscription_url,                             topic.get('title', ''))   class writer(object):      def __init__(self, opt):         path = opt.output[opt.output.index(":") + 1:]         self._logger = logging.getLogger("myplugin")         handler = logging.FileHandler(path)         handler.setFormatter(logging.Formatter(opt.format, opt.datefmt))         self._logger.addHandler(handler)      def __enter__(self):         return WriteMyPlugin(self._logger)      def __exit__(self, *exc_info):         pass  

ссылка на оригинал статьи http://habrahabr.ru/post/182712/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *