laclefblog logo

Sun, 12 Oct 2008

Twitxrのメッセージをバックアップ

今の段階で、僕がTwitxrにポストしたメッセージ数は1216、もう少し前から使っているTwitterのメッセージ数は4194、となっている。Twitxrは未確認だが、Twitterは1ページ20個メッセージ表示で http://twitter.com/laclefyoshi?page=41 より古いメッセージを参照することが出来ない。Twitterが提供している検索サービスを使っても出ないし、どうやら古いメッセージはデータベースから削除しているか、どこかに隔離する仕様の様だ。

この手のサービスはマイクロブログ(micro-blogging)と言うのだから、メッセージはサービス上にあるが自分のログであるわけで、消されるのは面白くない。自分でバックアップを取って自分で再利用出来るようにしておくべきだろう。

Pythonで、TwitxrのAPIメソッドの1つであるgetUserTimelineを叩いて最新20個のメッセージ(XML)を取り出し、 lxml で解析、 sqlite3(pysqlite2) でデータベースに保存する。画像はバックアップしていない。

SQLiteのデータベースに保存するのは、XMLのまま保存するとかCSVに変換することも考えたが、ある程度サイズが大きくなることを考慮したため。

#!/usr/bin/python

import urllib
import lxml.etree
import sys
if sys.version_info[:2] >= (2, 5):
    import sqlite3
else:
    from pysqlite2 import dbapi2 as sqlite3

DB_FILE = 'twitxr_backup.db'

def init_db(con):
    con.execute("""CREATE TABLE twitxr(
        id INTEGER PRIMARY KEY,
        url TEXT,
        timestamp INTEGER,
        text TEXT,
        lat TEXT,
        lon TEXT,
        place TEXT)
    """)
    print("create db '%s'" % DB_FILE)

def update_db_fromxml(con):
    url = 'http://twitxr.com/api/rest/getUserTimeline?user=laclefyoshi'
    res = urllib.urlopen(url)
    t = lxml.etree.fromstring(res.read())
    for udelm in t.xpath('//update'):
        id = udelm.xpath('./@id')[0]
        cur = con.execute('SELECT * FROM twitxr WHERE id == %s' % id)
        if cur.fetchone() == None:
            url = udelm.xpath('./url')[0].text
            timestamp = udelm.xpath('./timestamp')[0].text
            text = udelm.xpath('./text')[0].text
            lat = udelm.xpath('./location/lat')[0].text
            lon = udelm.xpath('./location/lng')[0].text
            place = udelm.xpath('./location/place')[0].text
            con.execute("INSERT INTO twitxr VALUES(?, ?, ?, ?, ?, ?, ?)",
                (int(id), url, int(timestamp), text, lat, lon, place))
            con.commit()
            print("insert %s: %s" % (id, text))
        else:
            continue
        cur.close()

def main():
    con = sqlite3.connect(DB_FILE)
    try:
        init_db(con)
    except sqlite3.OperationalError:
        print("db '%s' is existed" % DB_FILE)
    update_db_fromxml(con)
    con.close()

main()

最新20個以前のメッセージは、HTMLを辿って、lxml.htmlで解析して取り出した。

これをcrontabで15分程度毎(メッセージのポスト数が20を越えないであろう時間間隔)に実行すれば、メッセージのバックアップが取れる。

ここまでするなら、Djangoでも使って自分専用マイクロブログサービスを作った方が安心で有意義なんじゃないかと、一瞬思った。