Firefox の places.sqlite からブックマークをとりだす
新規インストールしたマシンに旧マシンの Firefox のブックマークを移行しようと思いました。
で,どうせ bookmarks.html
でしょと思ってみてみたら,どうも内容が乏しい。
調べてみたら Firefox 3 では places.sqlite
というファイルにブックマークはじめアクセスした URL を記録しているみたいですね。
さいわいプロファイルフォルダをまるごととってあったので places.sqlite
を上書きしようかと思ったんですが,そうすると新マシンでとったブックマークがなくなってしまうのでちょっと困ります。
なので places.sqlite
の構造をみてみました。
% sqlite3 places.sqlite SQLite version 3.5.9 Enter ".help" for instructions sqlite> .tables moz_anno_attributes moz_favicons moz_keywords moz_annos moz_historyvisits moz_places moz_bookmarks moz_inputhistory moz_bookmarks_roots moz_items_annos
moz_bookmarks
というテーブルがあやしい。
sqlite> .headers on sqlite> SELECT * FROM moz_bookmarks; id|type|fk|parent|position|title|keyword_id|folder_type|dateAdded|lastModified 1|2||0|0||||1209528568635986|1219119864784935 2|2||1|0|ブックマークメニュー|||1209528568636177|1228180489548243 3|2||1|1|ブックマークツールバー|||1209528568636276|1225854151400802 4|2||1|2|タグ|||1209528568636372|1209528568636992 5|2||1|3|未整理のブックマーク|||1209528568636468|1224748978301927 ...... snip snip snip ...... 60|1|44|3|2|Google|0||1209530922956848|1212462725554602 ...... snip snip snip ......
ブックマークのタイトルはとれてますが,URL がみあたりません。
moz_bookmarks_roots
テーブルをみてみると,
sqlite> SELECT * FROM moz_bookmarks_roots; root_name|folder_id places|1 menu|2 toolbar|3 tags|4 unfiled|5
こちらではなかったみたい。これは名前のとおり,ブックマークツリーのルートみたいですね。
では,general な名前の moz_places
をみてみると,
sqlite> SELECT * FROM moz_places LIMIT 5; id|url|title|rev_host|visit_count|hidden|typed|favicon_id|frecency 1|place:queryType=0&sort=8&maxResults=10|queryType=0&sort=8 &maxResults=10||0|1|0||0 2|place:folder=BOOKMARKS_MENU&folder=UNFILED_BOOKMARKS &folder=TOOLBAR&queryType=1&sort=12 &excludeItemIfParentHasAnnotation=livemark%2FfeedURI&maxResults=10 &excludeQueries=1|folder=BOOKMARKS_MENU&folder=UNFILED_BOOKMARKS &folder=TOOLBAR&queryType=1&sort=12 &excludeItemIfParentHasAnnotation=livemark%2FfeedURI&maxResults=10 &excludeQueries=1||0|1|0||0 3|place:type=6&sort=14&maxResults=10|type=6&sort=14&maxResults=10||0|1|0||0 4|https://en-us.add-ons.mozilla.com/en-US/firefox/bookmarks/ |/en-US/firefox/bookmarks/|moc.allizom.sno-dda.su-ne.|0|0|0|1|140 5|http://en-us.www.mozilla.com/en-US/firefox/central/ |/en-US/firefox/central/|moc.allizom.www.su-ne.|0|0|0|2|140
こっちに URL が格納されているみたい。こちらにも title
がありますが,こちらはもともとの title なのかな。
で,当て推量してると moz_bookmarks
の fk
フィールドと moz_places
の id
フィールドが対応しているみたい((.schema
コマンドでスキーマをみてみましたけど,トリガ等で明示的にリレーションが設定されてはなかったです。))。
なので,結合して表示してみましょう。
sqlite> SELECT moz_places.url, moz_bookmarks.title ...> FROM moz_bookmarks, moz_places ...> WHERE moz_bookmarks.fk IS NOT NULL ...> AND moz_bookmarks.fk = moz_places.id ...> AND moz_places.url NOT LIKE 'place:%' ...> ORDER BY moz_bookmarks.id; url|title https://en-us.add-ons.mozilla.com/en-US/firefox/bookmarks/|Get Bookmark Add-ons http://en-us.www.mozilla.com/en-US/firefox/central/|Getting Started http://en-us.www.mozilla.com/en-US/firefox/help/|Help and Tutorials http://en-us.www.mozilla.com/en-US/firefox/customize/|Customize Firefox http://en-us.www.mozilla.com/en-US/firefox/community/|Get Involved http://en-us.www.mozilla.com/en-US/firefox/about/|About Us http://www.google.co.jp/|Google
おー。いい感じです。
じゃあこっからエクスポートするスクリプトを書いてみる。
#!/usr/bin/perl use strict; use warnings; use DBI; my $file = shift; if (! defined $file) { die "database places.sqlite not specified"; } my $dbh = DBI->connect("dbi:SQLite:dbname=${file}") or die $DBI::errstr; my $sth = $dbh->prepare(<<'END_SQL') SELECT moz_places.url, moz_bookmarks.title FROM moz_bookmarks, moz_places WHERE moz_bookmarks.fk IS NOT NULL AND moz_bookmarks.fk = moz_places.id AND moz_places.url NOT LIKE ? ORDER BY moz_bookmarks.id; END_SQL or die $dbh->errstr; $sth->execute('place:%') or die $dbh->errstr; my @items; while (my $rec = $sth->fetchrow_hashref()) { #use YAML; #print Dump($rec); my ($url, $title) = map { $rec->{$_} } qw( url title ); for ($url) { s'"'"'go; } for ($title) { s'&'&'go; s'<'<'go; s'>'>'go; } push @items, <<"END_ITEM"; <DT><A HREF="${url}">${title}</A> END_ITEM } if (@items) { my $items = join q{}, @items; print <<"END_HTML"; <!DOCTYPE NETSCAPE-Bookmark-file-1> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> <TITLE>Bookmarks</TITLE> <H1>Bookmarks</H1> <DL><p> ${items} </DL><p> END_HTML }
で
% perl bookmark.pl $(BOOKMARKPROFILE)/places.sqlite
実行すると,
<!DOCTYPE NETSCAPE-Bookmark-file-1> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> <TITLE>Bookmarks</TITLE> <H1>Bookmarks</H1> <DL><p> <DT><A HREF="https://en-us.add-ons.mozilla.com/en-US/firefox/bookmarks/">Get Bookmark Add-ons</A> <!-- snip snip snip --> </DL><p>
うまくできました。
あとはこのファイルから不要な項目を削って「ブックマークの管理」から「HTML からインポート」すればいいはず。
ほんとうはブックマークフォルダの階層構造もとれるんでしょうけど,面倒だしそこまでもとめていない*1のでこれでいいやと思いました。
あと,favicon もとろうと思えばとれますが,bookmarks.html
の場合,内部にアイコンがうめこまれているのに対し,places.sqlite
の場合,moz_favicons
テーブルからアイコンの URL を取得してブラウザキャッシュのアイコンファイルを利用しているのではないかなー。
*1:おおかたのブックマークは Gmarks にまかせているので,メインのブックマークはそんなにないのです。