LDRのpinをInstapaperにポストするpythonスクリプト
LDRのAPIを使うにはログインが必要だが、python版mechanizeを使うとcookieなどの処理を意識せず簡単にできる。
#! /usr/bin/env python # coding: utf-8 import mechanize import json import urllib def account(service_name): import sys, os import yaml # スクリプトのディレクトリ dir = os.path.abspath(os.path.dirname(__file__)) return yaml.load(open(dir + '/accounts.yaml'))[service_name] class LDRbrowser(object): LD_LOGIN_URL = 'https://member.livedoor.com/login/index' LD_READER_URL = 'http://reader.livedoor.com/' LD_GET_PIN_URL = 'http://reader.livedoor.com/api/pin/all' LD_REMOVE_PIN_URL = 'http://reader.livedoor.com/api/pin/remove' def __init__(self, username, password): ''' インスタンス生成時にログイン ''' self.client = mechanize.Browser() self.client.open(self.LD_LOGIN_URL) self.client.select_form('loginForm') self.client['livedoor_id'] = username self.client['password'] = password self.client.submit() # ApiKeyを取得するため一度LDRにアクセスし、クッキーを解析 info = str(self.client.open(self.LD_READER_URL).info()) for line in info.split('\n'): key = 'reader_sid=' if key in line: self.apikey = line[line.find(key) + len(key):line.find(';')] def get_pin(self): # 第二引数Dataを与えるとPOSTメソッドになる self.client.open(self.LD_GET_PIN_URL, '') # JSON形式がかえってくる pin_json = self.client.response().read() # JSON形式のデータをdictに変換 list = json.loads(pin_json) return list def remove_pin(self, entry_list): ''' entry_listはキー link を含む辞書のリスト entry_list = [{'link': 'http://...'}, {...}, ...] 戻り値はURLとレスポンスコードの辞書 ''' result = {} pd = {'ApiKey': self.apikey} for entry in entry_list: pd['link'] = entry['link'] params = urllib.urlencode(pd) response = self.client.open(self.LD_REMOVE_PIN_URL, params) result[entry['link']] = response.code return result def add_to_instapaper(entry_list, username, password): ''' entry_list はキー link, title を含む辞書のリスト entry_list = [{'link': 'http://...', 'title': '...'}, {...}, ...] 戻り値はURLとレスポンスコードの辞書 ''' INSTAPAPER_API_URL = 'https://www.instapaper.com/api/add' pd = {'username':username, 'password':password} result = {} for entry in entry_list: pd['url'] = entry['link'] pd['title'] = entry['title'].encode('UTF-8') params = urllib.urlencode(pd) response = urllib.urlopen(INSTAPAPER_API_URL, params) result[entry['link']] = response.code return result if __name__ == '__main__': from datetime import datetime # Livedoorにログイン ldac = account('livedoor') br = LDRbrowser(ldac['username'], ldac['password']) # ピン一覧を取得 entries = br.get_pin() # Instapaperにpost # post成功したものをピンから削除 ipac = account('instapaper') ip_result = add_to_instapaper(entries, ipac['username'], ipac['password']) remove_urls = [] log = [] for url, code in ip_result.iteritems(): if 200 <= code and code < 300: remove_urls.append({'link': url}) log.append('%s Post to Instapaper: %s %s' % (datetime.now(), url, code)) pin_result = br.remove_pin(remove_urls) for url, code in pin_result.iteritems(): log.append('%s Remove from Pin: %s %s' % (datetime.now(), url, code)) f = open('/var/log/ldrpin_to_instapaper_log.txt', 'a') if log: f.write('\n'.join(log) + '\n') f.close()
インスタンス生成時にログインし、セッションとapikeyを使い回すようにした。
が、ログイン失敗時などの処理をしておくべきかもしれない。今後の課題か。
スクリプトと同じディレクトリにLivedoorとInstapaperのID, Passwordを書いたYAMLファイルを置いておく
accounts.yaml
livedoor: username: xxxx password: xxxx instapaper: username: xxxx password: xxxx
このスクリプトを10分くらいの間隔で実行するようcronに登録しておくと、iPhone上で
- LDRをチェック -> pin登録 -> 軽量かつオフライン閲覧可能なInstapaperアプリで読む
ことができる。
Livedoorの二重ログインが問題になるかと思ったが、数日使ってみたところ特に問題なく使えている。
LDRのAPIについては以下のエントリが参考になる。
Livedoor ReaderのAPIを探して全部まとめてみた。 - ガジェカツ~在宅SEのガジェット活動ブログ~
python版mechanizeの使い方は以下のエントリの、はてなにログインするスクリプトを参考にした。
はてなのバックアップスクリプトをPythonに移植してみた - とある誰かの覚え書き