やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

はてなフォトライフの全データURLをRSSで取得する方法を調べてみた

APIでなくRSSで。

はてなフォトライフAPI

はてなフォトライフAtomAPI - Hatena Developer Center

APIでは全データを取得することができない。

フォトライフ管理ページ

http://f.hatena.ne.jp/my/Hatena%20Blog/

ログイン

はてなサイトでのログインが必要。

画像リンク取得

http://www.kazumiso.info/entry/get-hatena-photo-url

取得方法 URL
フォトライフサイトのリンク http://f.hatena.ne.jp/ytyaru/20170228130132?key=qBecFEQpzxwy3Cvf
RSS http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132.gif
編集プレビュー右クリックURLコピー https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132.gif

拡張子が付いている形式だと直リンクできるものに見える。それが望ましい。

RSSから取得する

RSSリンクを取得する。

http://f.hatena.ne.jp/{HatenaId}/Hatena%20Blog/rss

私の場合は以下。

http://f.hatena.ne.jp/ytyaru/Hatena%20Blog/rss

page

そのURLにURLパラメータpage=1を付与すると50件ずつ取得できる。ソートは最新日時順。

のようにする。取得できなくなるまでpageをインクリメントしていけばいい。

sort

sort=oldのようにすると日時の昇順になる。

引数 ソート
sort=old 日時の昇順(古い順)
sort=new 日時の降順(新しい順)

RSS形式

<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF
    xmlns="http://purl.org/rss/1.0/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:hatena="http://www.hatena.ne.jp/info/xmlns#"
    xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
    xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
    xml:lang="ja">
<channel rdf:about="http://f.hatena.ne.jp/ytyaru/Hatena%20Blog/rss">
    <title>ytyaru's fotolife - Hatena Blog</title>
    <link>http://f.hatena.ne.jp/ytyaru/Hatena%20Blog/</link>
    <description>ytyaru's fotolife - Hatena Blog</description>
    <openSearch:totalResults>1075</openSearch:totalResults>
    <openSearch:startIndex>1</openSearch:startIndex>
    <openSearch:itemsPerPage>50</openSearch:itemsPerPage>
    <items>
    <rdf:Seq>
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228130132" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228130124" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228130110" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228095350" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228095133" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228095119" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228090322" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228090235" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228073154" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170228073146" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227183618" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227183537" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227183521" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174700" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174613" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174347" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174332" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174247" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174230" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174218" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174151" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227174116" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227172354" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227172343" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227172334" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227172326" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227172318" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227151718" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227151533" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170227151448" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170226150333" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225142702" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225142647" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225142627" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225142618" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225135135" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225135126" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225135118" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225135107" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225135059" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225134959" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225134944" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225123148" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170225123129" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170224123525" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170224085715" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170224084022" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170224084015" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170224084009" />
        <rdf:li rdf:resource="http://f.hatena.ne.jp/ytyaru/20170224083959" />
    </rdf:Seq>
    </items>
</channel>
<item rdf:about="http://f.hatena.ne.jp/ytyaru/20170228130132">
    <title>20170228130132</title>
    <link>http://f.hatena.ne.jp/ytyaru/20170228130132</link>
    <description><![CDATA[<a href="http://f.hatena.ne.jp/ytyaru/20170228130132"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_m.jpg" alt="20170228130132"></a>]]></description>
    <content:encoded><![CDATA[<a href="http://f.hatena.ne.jp/ytyaru/20170228130132"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132.gif" alt="20170228130132"></a>]]></content:encoded>
    <dc:date>2017-02-28T13:01:32+09:00</dc:date>
    <hatena:imageurl>http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132.gif</hatena:imageurl>
    <hatena:imageurlsmall>http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_m.jpg</hatena:imageurlsmall>
    <hatena:imageurlmedium>http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_120.jpg</hatena:imageurlmedium>
    <hatena:syntax>f:id:ytyaru:20170228130132g:image</hatena:syntax>
    <hatena:colors>
        <hatena:color>white</hatena:color>
        <hatena:color>white</hatena:color>
    </hatena:colors>
</item>
...<item>が49件分続く...
</rdf:RDF>

ItemId

はてなフォトライフAtomAPI - Hatena Developer Center

サンプルのXXXXXXXXXXXXXXは画像のURLにおける末尾の数値部に置き換えてください。 サンプルのYYYYYYは画像をアップロードした写真があるフォルダ名に置き換えてください。

XXXXXXXXXXXXXXは14文字。20170224084022のような値と思われる。これは日時データ。YYYYmmddHHMMSSの14文字。どうやらアップロード日時をそのままItemIdとして使っているらしい。

レスポンス

画像URL

サイズ 名前 URL
hatena:imageurl http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132.gif
hatena:imageurlsmall http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_m.jpg
hatena:imageurlmedium http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_120.jpg
http://cdn-ak.f.st-hatena.com/{FileTypeGroup}/fotolife/{IdFirst}/{HatenaId}/{YYYYmmdd}/{YYYYmmddHHMMSS}.{ext}
http://cdn-ak.f.st-hatena.com/{FileTypeGroup}/fotolife/{IdFirst}/{HatenaId}/{YYYYmmdd}/{YYYYmmddHHMMSS}_m.{ext}
http://cdn-ak.f.st-hatena.com/{FileTypeGroup}/fotolife/{IdFirst}/{HatenaId}/{YYYYmmdd}/{YYYYmmddHHMMSS}_120.{ext}
項目 説明
{FileTypeGroup} 画像=image。(動画=movieと思ったが直リンできない。存在しない)
{IdFirst} はてなIDの頭文字。1文字目。と思われる。私の場合はy
{HatenaId} 私の場合はytyaru
{YYYYmmdd} 画像のアップロード日付。
{YYYYmmddHHMMSS} 画像のアップロード日時。{ItemId}と同一。
{ext} ファイルの拡張子。縮小画像はすべてjpgと思われる。元画像はアップロードしたときと同じ。

上記のことから、{HatenaId}と{ItemId}と{ext}があれば画像URLを組み立てることができると思われる。

DBをどうするか。

将来の拡張に備える|URL変更に備えてそのままのURLを保存する 重複を省く|URLの重複部分を割けるため{ItemId}と{ext}のみ保存する

<hatena:imageurl>http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132.gif</hatena:imageurl>
    <hatena:imageurlsmall>http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_m.jpg</hatena:imageurlsmall>
    <hatena:imageurlmedium>http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytyaru/20170228/20170228130132_120.jpg</hatena:imageurlmedium>

画面キャプチャが多い。縮小すると文字などが見えなくなってしまうため、あまり意味がない。ただ、一覧するときは便利。

フォトライフ記法

<hatena:syntax>f:id:ytyaru:20170228130132g:image</hatena:syntax>
f:id:{HatenaId}:{ItemId}{FileType}:{FileTypeGroup}
項目 上記例の場合 説明
HatenaId ytyaru
ItemId 20170228130132 アップロード日時がItemIdになる
FileType g gif=g, png=p, jpeg=j
FileTypeGroup image 画像ならimage

気になること

title, alt属性値

画像のメタデータとして、HTMLにおけるtitle, alt属性値を設定できないか。

属性 説明
title マウスオーバーしたときに表示されるテキスト。
alt 画像非表示の環境で代わりに表示されるテキスト。

フォトライフ記法では可能になったらしいが。

はてなフォトライフの画像を貼り付けるときに、フォトライフ記法でaltとtitleを指定できるようにしました(はてな記法モード、Markdownモード) - はてなブログ開発ブログ

もしDBに登録すれば検索できるようになりそう。

もしくは手順書などの場合、1ファイルとしてまとめてしまいたい。

課題

肝心の画像データをBLOBで保存することができていない。

URLが判明したのでHTTPのGETで取得できるのだろうか。

所感

まさかAPIでなくRSSを使うことになるとは。仕様書にはドメイン名が未記載などの不足があるので、もしかするとAPIにも全アイテムを取得する機能が存在するのかもしれない。