読者です 読者をやめる 読者になる 読者になる

SafariのReadingListの値を取得する

iPhoneだと割とsafariを利用し、あとで読むものは片っ端から Reading List に突っ込んでいたりします。
f:id:rochefort:20170204163959p:plain
 
ですが、PCで見る場合はChromeが多いので、SafariのReading Listの値を引っこ抜けないかどうかを調べてみました。

どこに保存されているか

How do I export my safari 5.1 Reading list? | Official Apple Support Communities
~/Library/Safari/Bookmarks.plist だそうです。
しかも、以下でxmlに変換できるそうです。これは知りませんでした。

/usr/bin/plutil -convert xml1 -o - ~/Library/Safari/Bookmarks.plist

構造を確認して見る

bookmarkと混在していますが、key=ReadingList 周辺にあるようです。
titleは key=ReadingListNonSync のdictに key=Title で格納されているようです。
ですが時々値が入っていなかったりします。
ですので、key=URIDictionary のdictに key=Title で格納されているもの(この値はtilteだったりurlだったりする)を使ってみました。
urlは key=URLString に格納されています。

<dict>
  <key>ReadingList</key>
  <dict>
    <key>DateAdded</key>
    <date>2017-01-31T11:05:08Z</date>
    <key>PreviewText</key>
    <string>みなさんこんにちわ。 メドピアでエンジニアをやっている内田と申します。 現在メドピアではPHPで作られたレガシーな独自フレームワーク (以下FW) からRailsへと移行するプロジェクトが進んでいます。 今回は移行に向けて行ったことについて共有したいと思います。 移行の計画 メドピア株式会社では、医師限定のコミュニティ…</string>
    <key>SourceBundleID</key>
    <string>com.atebits.Tweetie2</string>
    <key>SourceLocalizedAppName</key>
    <string>Twitter</string>
  </dict>
  <key>ReadingListNonSync</key>
  <dict>
    <key>ArchiveOnDisk</key>
    <true/>
    <key>DateLastFetched</key>
    <date>2017-02-01T05:07:48Z</date>
    <key>FetchResult</key>
    <integer>1</integer>
    <key>Title</key>
    <string>レガシーな独自フレームワークから脱却してRailsへ徐々に移行している話</string>
    <key>neverFetchMetadata</key>
    <false/>
    <key>siteName</key>
    <string>メドピア開発者ブログ</string>
  </dict>
  <key>URIDictionary</key>
  <dict>
    <key>title</key>
    <string>http://tech.medpeer.co.jp/entry/2017/01/31/004227</string>
  </dict>
  <key>URLString</key>
  <string>http://tech.medpeer.co.jp/entry/2017/01/31/004227</string>
  <key>WebBookmarkType</key>
  <string>WebBookmarkTypeLeaf</string>
  <key>WebBookmarkUUID</key>
  <string>58B295F7-1BC2-46DB-BD54-9084F779FA01</string>
</dict>

抜いて見る

require "nokogiri"
xml = `/usr/bin/plutil -convert xml1 -o - ~/Library/Safari/Bookmarks.plist`
doc = Nokogiri::XML(xml)

doc.xpath("//key[text() = 'ReadingList']/..").each do |elm|
  non_sync_title = elm.xpath("key[text() = 'ReadingListNonSync']/following-sibling::dict/key[text() = 'Title']/following-sibling::string[1]").text
  url_dic_title = elm.xpath("key[text() = 'URIDictionary']/following-sibling::dict/string[1]").text
  title = non_sync_title.empty? ? url_dic_title : non_sync_title
  link = elm.xpath("key[text() = 'URLString']/following-sibling::string[1]").text
  puts "<li><a href=\"#{link}\">#{title}</a></li>"
end

こんな感じ。
f:id:rochefort:20170204164754p:plain
めでたしめでたし。