Hatena::ブログ(Diary)

もの置き処 このページをアンテナに追加

2011-05-09

Firefoxの過去履歴を統合する

履歴。それは過去と現在をつなぐ連続的な生きた軌跡。

数カ月前、数年前に何を思い、何に挑戦していたか。

プロジェクトフォルダや単なるバックアップからでは見いだせない過去の記憶。

昔あのページを見た自分と今あのページを見直す自分が重なり、ふっと湧き出る覚えと「あのとき」とは異なる感覚。

螺旋階段の一巻き上を登っているような、浮遊感。あるいは上位感覚。


昔の履歴を見返すと参考になることは多い。もはや資産とも言えるのではないか。


などと意味のわからないことばを並べて遊んだあとに本題に入りますw(ぇ

Firefoxの昔の消えた履歴を今のプロファイルにコピーする」Pythonスクリプトを書いてみました。

消えた履歴とは保存日数が経過した結果Firefoxが自動的にに削除した分を指します。違うプロファイルの履歴とは内部の通し番号がかち合うので多分正しく統合できません。

いろいろ拡張した結果、どちらかというと情報表示スクリプトっぽくなっています。

"""
Firefoxが自動的に削除した過去の履歴を融合する
[[同じプロファイルでないとデータ不整合になる可能性大]]
$ その前にabout:configの設定を忘れずに
browser.history_expire_days.mirror 365000
browser.history_expire_days_min 365000
browser.history_expire_sites 1000000
browser.history_expire_visits 1000000
places.history.expiration.max_pages 1000000
places.history.expiration.interval_seconds 4200000000
$ 使い方
OLDに昔の、NEWに今の、DSTにはNEWを複製してOLDの履歴を追加するファ
イルの名前を記述しておく。↓
プロファイルフォルダのplaces.sqlite-shm, places.sqlite-walは消す
このファイルを全部インタプリタにコピペして
main(test=True)またはmain()で開始する
"""
OLD = "/home/ユーザ名/デスクトップ/places_old.sqlite"
NEW = "/home/ユーザ名/デスクトップ/places_new.sqlite"
DST = "/home/ユーザ名/デスクトップ/places.sqlite"

import shutil
from time import sleep
import sqlite3

GETPLA = "SELECT * from moz_places"  # core
GETHIS = "SELECT * from moz_historyvisits"  # history detail
GETBOK = "SELECT * from moz_bookmarks"
GETBKR = "SELECT * from moz_bookmarks_roots"
GETFAV = "SELECT * from moz_favicons"
GETKWS = "SELECT * from moz_keywords"
GETANO = "SELECT * from moz_annos"  # annotation for pages
GETCHR = "SELECT * from moz_annos WHERE anno_attribute_id=9"
GETATO = "SELECT * from moz_anno_attributes"
GETATR = """SELECT * from moz_anno_attributes LEFT JOIN (SELECT 
anno_attribute_id, count(*) from moz_annos GROUP BY 
anno_attribute_id) ON moz_anno_attributes.id=anno_attribute_id"""
GETITM = "SELECT * from moz_items_annos"  # annotation for bookmarks
INSPLA = "INSERT into moz_places values(?,?,?,?,?,?,?,?,?,?,?)"
INSHIS = "INSERT into moz_historyvisits values(?,?,?,?,?,?)"
DELCHR = "DELETE from moz_annos WHERE anno_attribute_id=9"

def count(cursor):
	print "  places: %s" % len(list(cursor.execute(GETPLA)))
	print "  historyvisits: %s" % len(list(cursor.execute(GETHIS)))
	print "  (bookmarks: %s)" % len(list(cursor.execute(GETBOK)))
	print "  (bookmarks_roots: %s)" % len(list(cursor.execute(GETBKR)))
	#for r in cursor.execute(GETBKR): print "   ", r
	print "  (favicons: %s)" % len(list(cursor.execute(GETFAV)))
	print "  (keywords: %s)" % len(list(cursor.execute(GETKWS)))
	print "  (annotations: %s)" % len(list(cursor.execute(GETANO)))
	for r in cursor.execute(GETATR):
		print "    %s %s * %s" % (r[0], r[1], r[3] or 0)	
	print "  (anno_attributes: %s)" % len(list(cursor.execute(GETATO)))
	#for r in cursor.execute(GETATO): print "   ", r
	print "  (items_annos: %s)" % len(list(cursor.execute(GETITM)))
	#for r in cursor.execute(GETITM): print r[4]

def copy_places(from_cur, to_cur):
	err, ok = 0, 0
	for row in from_cur.execute(GETPLA):
		try:
			row = list(row)
			if len(row) == 10:
				row.append(None)
			to_cur.execute(INSPLA, row)
			ok += 1
		except Exception, e:
			err += 1
	print "duplicated: %s, added: %s" % (err, ok)

def copy_history(from_cur, to_cur):
	err, ok = 0, 0
	for row in from_cur.execute(GETHIS):
		try:
			to_cur.execute(INSHIS, row)
			ok += 1
		except Exception, e:
			err += 1
	print "duplicated: %s, added: %s" % (err, ok)

def remove_charsets(cursor):
	ok = len(list(cursor.execute(GETCHR)))
	cursor.execute(DELCHR)
	print "character sets by URI removed: %s" % ok

def main(test=False):
	shutil.copyfile(NEW, DST)
	conn = sqlite3.connect(OLD)
	newc = sqlite3.connect(DST)
	oldcur = conn.cursor()
	newcur = newc.cursor()
	
	print "old:"
	count(oldcur)
	print "new:"
	count(newcur)
	
	if not test:
		print "copying places"
		copy_places(oldcur, newcur)
		print "copying histories"
		copy_history(oldcur, newcur)
		print "removing charsets"
		remove_charsets(newcur)
		print "commiting"
		newc.commit()
		print "vacumming"		
		newcur.execute("VACUUM")
		print "reindexing"
		newcur.execute("REINDEX")
		newcur.commit()
		print "after:"
		count(newcur)
	
	print "closing source DB"
	conn.close()
	print "closing destination DB"
	newc.close()
	
	print "finish."

if __name__ == '__main__':
    main()
# main(test=True)

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/moondial0/20110509/1304954785