はてなフォトライフに投稿した画像の情報はRSSフィードで取得できる。
これを利用して、Ruby と wget と bash でバックアップする。

今回の環境。


$ uname -mrsv
Linux 2.6.26-2-amd64 #1 SMP Tue Jan 25 05:59:43 UTC 2011 x86_64
 
$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]

はてなフォトライフ投稿情報RSSを取得して、wgetで取得するファイルのリストを生成するRubyスクリプト。
バックアップするはてなフォトライフのフォルダは、設定で公開範囲をパブリックにしておく必要がある。


$ cat ./hatena_f_backup.rb
#!/usr/bin/env ruby
$KCODE='u'
 
require 'open-uri'
require 'uri'
require "rexml/document"
 
# ユーザー名
username = 'nilab'
# フォルダ
folders = ['', 'coco', 'coco-o', 'Mono']
 
# 指定したフォルダのRSSを全部取得
folders.each{|folder|
 
  # RSSのURL
  if folder == ''
    rss = "http://f.hatena.ne.jp/#{username}/rss"
  else
    rss = "http://f.hatena.ne.jp/#{username}/#{folder}/rss"
  end
 
  # 出力する情報ファイル
  finfo = open("_info_#{username}_#{folder}.txt",'w')
  # 出力するwget用ファイル
  fwget = open("_wget_#{username}_#{folder}.txt",'w')
 
  # 1ページ目から順番に取得
  page = 1
  while true
    # 連続でアクセスしてbanされないように
    sleep(1)
    # RSSのURL
    url = "#{rss}?page=#{page}"
    $stderr.puts url
    # RSS文字列を取得
    rssstr = ''
    open(url){|fi|
      rssstr = fi.read()
    }
    # RSS文字列を解析
    doc = REXML::Document.new(rssstr)
    items = doc.get_elements('rdf:RDF/item')
    break if items.size == 0 # アイテムが0件だったら終了
    items.each{|item|
      # 画像のURLなどの情報を抜き出す
      link = item.get_text('link').value
      imageurl = item.get_text('hatena:imageurl').value
      # 情報を出力
      finfo.puts "#{link}\t#{imageurl}\n"
      # wget用の情報を出力
      # 1秒ウェイトで画像ファイルを取得していく
      outputfile = URI.parse(imageurl).path.split('/').last()
      fwget.puts "wget -x -nc -O #{outputfile} #{imageurl}\n"
      fwget.puts "sleep 1\n"
    }
    # RSSファイルを保存する
    open("#{username}_#{folder}_#{page}.xml",'w'){|fo|
      fo.write(rssstr)
    }
    page += 1
  end
 
  finfo.close
  fwget.close
}

実行結果。


$ ruby ./hatena_f_backup.rb
http://f.hatena.ne.jp/nilab/rss?page=1
http://f.hatena.ne.jp/nilab/rss?page=2
http://f.hatena.ne.jp/nilab/coco/rss?page=1
http://f.hatena.ne.jp/nilab/coco/rss?page=2
http://f.hatena.ne.jp/nilab/coco/rss?page=3
http://f.hatena.ne.jp/nilab/coco-o/rss?page=1
http://f.hatena.ne.jp/nilab/coco-o/rss?page=2
http://f.hatena.ne.jp/nilab/coco-o/rss?page=3
http://f.hatena.ne.jp/nilab/coco-o/rss?page=4
http://f.hatena.ne.jp/nilab/coco-o/rss?page=5
http://f.hatena.ne.jp/nilab/Mono/rss?page=1
http://f.hatena.ne.jp/nilab/Mono/rss?page=2
http://f.hatena.ne.jp/nilab/Mono/rss?page=3
http://f.hatena.ne.jp/nilab/Mono/rss?page=4
http://f.hatena.ne.jp/nilab/Mono/rss?page=5
http://f.hatena.ne.jp/nilab/Mono/rss?page=6
http://f.hatena.ne.jp/nilab/Mono/rss?page=7
http://f.hatena.ne.jp/nilab/Mono/rss?page=8
http://f.hatena.ne.jp/nilab/Mono/rss?page=9
http://f.hatena.ne.jp/nilab/Mono/rss?page=10
http://f.hatena.ne.jp/nilab/Mono/rss?page=11
http://f.hatena.ne.jp/nilab/Mono/rss?page=12
http://f.hatena.ne.jp/nilab/Mono/rss?page=13
http://f.hatena.ne.jp/nilab/Mono/rss?page=14
http://f.hatena.ne.jp/nilab/Mono/rss?page=15
http://f.hatena.ne.jp/nilab/Mono/rss?page=16
http://f.hatena.ne.jp/nilab/Mono/rss?page=17
http://f.hatena.ne.jp/nilab/Mono/rss?page=18
http://f.hatena.ne.jp/nilab/Mono/rss?page=19
http://f.hatena.ne.jp/nilab/Mono/rss?page=20
http://f.hatena.ne.jp/nilab/Mono/rss?page=21
http://f.hatena.ne.jp/nilab/Mono/rss?page=22
http://f.hatena.ne.jp/nilab/Mono/rss?page=23
http://f.hatena.ne.jp/nilab/Mono/rss?page=24
http://f.hatena.ne.jp/nilab/Mono/rss?page=25
http://f.hatena.ne.jp/nilab/Mono/rss?page=26
http://f.hatena.ne.jp/nilab/Mono/rss?page=27
http://f.hatena.ne.jp/nilab/Mono/rss?page=28
http://f.hatena.ne.jp/nilab/Mono/rss?page=29
http://f.hatena.ne.jp/nilab/Mono/rss?page=30
http://f.hatena.ne.jp/nilab/Mono/rss?page=31
http://f.hatena.ne.jp/nilab/Mono/rss?page=32
http://f.hatena.ne.jp/nilab/Mono/rss?page=33
http://f.hatena.ne.jp/nilab/Mono/rss?page=34

ダウンロードしたRSSや、wget用に出力したファイル。


$ ls
_info_nilab_.txt       nilab_Mono_13.xml  nilab_Mono_25.xml  nilab_Mono_7.xml
_info_nilab_Mono.txt   nilab_Mono_14.xml  nilab_Mono_26.xml  nilab_Mono_8.xml
_info_nilab_coco-o.txt nilab_Mono_15.xml  nilab_Mono_27.xml  nilab_Mono_9.xml
_info_nilab_coco.txt   nilab_Mono_16.xml  nilab_Mono_28.xml  nilab__1.xml
_wget_nilab_.txt       nilab_Mono_17.xml  nilab_Mono_29.xml  nilab_coco-o_1.xml
_wget_nilab_Mono.txt   nilab_Mono_18.xml  nilab_Mono_3.xml   nilab_coco-o_2.xml
_wget_nilab_coco-o.txt nilab_Mono_19.xml  nilab_Mono_30.xml  nilab_coco-o_3.xml
_wget_nilab_coco.txt   nilab_Mono_2.xml   nilab_Mono_31.xml  nilab_coco-o_4.xml
hatena_f_backup.rb     nilab_Mono_20.xml  nilab_Mono_32.xml  nilab_coco_1.xml
nilab_Mono_1.xml       nilab_Mono_21.xml  nilab_Mono_33.xml  nilab_coco_2.xml
nilab_Mono_10.xml      nilab_Mono_22.xml  nilab_Mono_4.xml
nilab_Mono_11.xml      nilab_Mono_23.xml  nilab_Mono_5.xml
nilab_Mono_12.xml      nilab_Mono_24.xml  nilab_Mono_6.xml

bash + wget で写真/画像ファイルをダウンロード。


$ bash _wget_nilab_.txt
$ bash _wget_nilab_Mono.txt
$ bash _wget_nilab_coco-o.txt
$ bash _wget_nilab_coco.txt

参考までに、nilab_coco_2.xml (http://f.hatena.ne.jp/nilab/coco/rss?page=2) の中身(一部加工)。


<?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/nilab/coco/rss">
  <title>nilab's fotolife - coco</title>
  <link>http://f.hatena.ne.jp/nilab/coco/</link>
  <description>nilab's fotolife - coco</description>
  <openSearch:totalResults>52</openSearch:totalResults>
  <openSearch:startIndex>51</openSearch:startIndex>
  <openSearch:itemsPerPage>50</openSearch:itemsPerPage>
  <items>
  <rdf:Seq>
    <rdf:li rdf:resource="http://f.hatena.ne.jp/nilab/20100719171138" />
    <rdf:li rdf:resource="http://f.hatena.ne.jp/nilab/20100715135007" />
  </rdf:Seq>
  </items>
</channel>
<item rdf:about="http://f.hatena.ne.jp/nilab/20100719171138">
  <title>20100719171138</title>
  <link>http://f.hatena.ne.jp/nilab/20100719171138</link>
  <description><![CDATA[<a href="http://f.hatena.ne.jp/nilab/20100719171138"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138_m.jpg?1304256839" alt="20100719171138"></a>]]></description>
  <content:encoded><![CDATA[<a href="http://f.hatena.ne.jp/nilab/20100719171138"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138.jpg?1304256839" alt="20100719171138"></a>]]></content:encoded>
  <dc:date>2010-07-19T17:11:38+09:00</dc:date>
  <hatena:imageurl>http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138.jpg?1304256839</hatena:imageurl>
  <hatena:imageurlsmall>http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138_m.jpg?1304256839</hatena:imageurlsmall>
  <hatena:imageurlmedium>http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138_120.jpg?1304256839</hatena:imageurlmedium>
  <hatena:syntax>f:id:nilab:20100719171138j:image</hatena:syntax>
  <hatena:colors>
    <hatena:color>white</hatena:color>
    <hatena:color>black</hatena:color>
  </hatena:colors>
</item>
<item rdf:about="http://f.hatena.ne.jp/nilab/20100715135007">
  <title>20100715135007</title>
  <link>http://f.hatena.ne.jp/nilab/20100715135007</link>
  <description><![CDATA[<a href="http://f.hatena.ne.jp/nilab/20100715135007"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007_m.jpg?1304256839" alt="20100715135007"></a>]]></description>
  <content:encoded><![CDATA[<a href="http://f.hatena.ne.jp/nilab/20100715135007"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007.jpg?1304256839" alt="20100715135007"></a>]]></content:encoded>
  <dc:date>2010-07-15T13:50:07+09:00</dc:date>
  <hatena:imageurl>http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007.jpg?1304256839</hatena:imageurl>
  <hatena:imageurlsmall>http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007_m.jpg?1304256839</hatena:imageurlsmall>
  <hatena:imageurlmedium>http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007_120.jpg?1304256839</hatena:imageurlmedium>
  <hatena:syntax>f:id:nilab:20100715135007j:image</hatena:syntax>
  <hatena:colors>
    <hatena:color>white</hatena:color>
    <hatena:color>yellow</hatena:color>
  </hatena:colors>
</item>
</rdf:RDF>

参考までに、 _info_nilab_coco.txt の中身(の一部)。


http://f.hatena.ne.jp/nilab/20100719171138  http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138.jpg?1304256839
http://f.hatena.ne.jp/nilab/20100715135007  http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007.jpg?1304256839

参考までに、 _wget_nilab_coco.txt の中身(の一部)。


wget -x -nc -O 20100719171138.jpg http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100719/20100719171138.jpg?1304256839
sleep 1
wget -x -nc -O 20100715135007.jpg http://cdn-ak.f.st-hatena.com/images/fotolife/n/nilab/20100715/20100715135007.jpg?1304256839
sleep 1

参考までに自分が現時点で投稿した画像ファイルは1827枚だった。
とりあえず、全ファイルバックアップ完了。

Ref.
- はてなフォトライフ - 無料・大容量、写真や動画を共有できるウェブアルバム
- nilab's fotolife

tags: ruby hatena backup wget

Posted by NI-Lab. (@nilab)