🔖

GoogleChromeのブックマークを登録日順に出力する

2022/10/06に公開

はじめに

GoogleChromeのブックマーク一覧を登録時の時系列順に並べて出力するpythonプログラムを実装しました。
ディレクトリの中にさらにディレクトリがあるような入れ子の場合にも対応しています。
ブックマークの情報には登録時のタイムスタンプが保存されているのでそれを使って並び替えています。

出力

後述のプログラムを実行した際の出力は以下のようになります。

3 urls
2022-10-04 Zenn|エンジニアのための情報共有コミュニティ https://zenn.dev/
2022-10-05 Zenn|エンジニアのための情報共有コミュニティ https://zenn.dev/
2022-10-06 Zenn|エンジニアのための情報共有コミュニティ https://zenn.dev/

プログラム

ブックマークの情報が格納されているファイルは自分の場合は~/.config/google-chrome/Default/Bookmarksでした。


from pathlib import Path
import json
from dataclasses import dataclass
from typing import Any, List, Optional

import datetime


def date_from_webkit(webkit_timestamp) -> datetime.datetime:
    # reference: https://www.epochconverter.com/webkit
    epoch_start = datetime.datetime(1601, 1, 1)
    delta = datetime.timedelta(microseconds=int(webkit_timestamp))
    return epoch_start + delta


@dataclass
class Bookmark:
    date_added: str
    guid: str
    id: str  # int
    name: str
    type: str
    url: str
    meta_info: Optional[Any] = None

    def info(self) -> str:
        return " ".join(
            (str(date_from_webkit(self.date_added).date()), self.name, self.url)
        )


bookmarks: List[Bookmark] = []


def dfs(entry):
    """traverse folder"""
    if entry["type"] == "folder":
        for next_entry in entry["children"]:
            dfs(next_entry)
    else:  # url
        bookmark = Bookmark(**entry)
        bookmarks.append(bookmark)


def main():

    bookmark_file_path = Path("~/.config/google-chrome/Default/Bookmarks").expanduser()
    with open(bookmark_file_path, "r") as f:
        data = json.load(f)
        for directory in data["roots"].values():
            dfs(directory)
    bookmarks.sort(key=lambda x: x.date_added)
    print(f"{len(bookmarks)} urls")
    for bookmark in bookmarks:
        print(bookmark.info())


if __name__ == "__main__":
    main()

さいごに

いつか読もうと思って登録したものの埋もれてしまっていたブックマークの存在に気づきました。

参考

https://kohashiiii.hatenablog.com/entry/2014/09/24/122346

https://www.epochconverter.com/webkit

Discussion