atomutilを使ってrubyでアメブロに投稿する方法
これまで、はてなダイアリー(atomutilを使ってrubyではてなダイアリーに投稿する方法 - 水清無魚(すいせいむぎょ))に引き続き、ライブドアのブログ投稿(atomutilを使ってrubyでライブドアのブログに投稿する方法 - 水清無魚(すいせいむぎょ))しました。
こんどは本丸というべきアメブロに投稿してみたいと思います。というのが、結構皆さん苦労されているみたいなんです。
はてなダイアリーやライブドアのブログと同じようにAtomPubの仕様ではあるのですが、ちょっと癖があって、パスワードをMD5ハッシュに変換しないといけないとか、nonceに使用できる文字列に制限があったりします。
しかし、カテゴリの設定に関しては結局わかりませんでした。Twitterのつぶやきを自動投稿するツールで設定されていたような気がするのですが・・・
とりあえず、タイトルと本文の投稿のみの現状を公開しておきます。
# -*- coding: utf-8 -*- # @see : http://d.hatena.ne.jp/lyokato/20071211/1197353609 # gem install atomutil require 'atomutil' # Livedoorブログやアメブロ対策のためオーバーライドし、戻り値としてLocationではなくステータスコードを返却するようにする class Atompub::Client def create_entry(post_uri, entry, slug=nil) unless entry.kind_of?(Atom::Entry) entry = Atom::Entry.new :stream => entry end service = @service_info.get(post_uri) # Livedoorブログの場合、serviceが取得できなくてservice.allows_category?でエラーになるので、if serviceでくくる if service unless entry.categories.all?{ |c| service.allows_category?(c) } raise RequestError, "Forbidden Category" end end create_resource(post_uri, entry.to_s, Atom::MediaType::ENTRY.to_s, slug) return @res.code rescue Atompub::ResponseError #=> rs # アメブロでは正常に投稿できても@res['Location']が空になってResponseErrorになるので捕獲する return @res.code end end # アメブロでnonceに英数以外が含まれるとエラーになるのでオーバーライド class Atompub::Auth::Wsse def gen_token # 以下で生成される文字列ではAmebloの場合エラーとなる #nonce = Array.new(10){rand(0x100000000)}.pack('I*') nonce = [*1..9, *'A'..'Z', *'a'..'z'].sample(16).join nonce_base64 = [nonce].pack('m').chomp now = Time.now.utc.iso8601 digest = [Digest::SHA1.digest(nonce + now + @password)].pack('m').chomp sprintf(%Q<UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s">, @username, digest, nonce_base64, now) end end def entry(id, password, title, content, category=nil) # アメブロに限り、パスワード文字列のmd5ハッシュ値化必要 # @see : http://senpai4.blog29.fc2.com/blog-entry-452.html password = Digest::MD5.hexdigest(password) auth = Atompub::Auth::Wsse.new :username => id, :password => password client = Atompub::Client.new :auth => auth service = client.get_service("http://atomblog.ameba.jp/servlet/_atom/blog") ns = Atom::Namespace.new(:uri => 'http://purl.org/atom/ns#') links = service.getlist(ns, 'link') href = nil links.each do |link| if link.attributes['rel'] == 'service.post' href = link.attributes['href'] break end end # 自動改行にはならないので(ブログ側の設定次第?) content = content.gsub(/\n/, '<br/>'); # カテゴリの設定方法は不明 new_entry =<<EOM <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://purl.org/atom/ns#"> <title>#{title}</title> <content type="application/xhtml+xml"> <![CDATA[#{content}]]> </content> </entry> EOM return client.create_entry(href, new_entry) end title = "テスト" content =<<EOM <b>太字ですか?</b> 改行されていますか? EOM puts entry('<ログインID>', '<パスワード>', title, content)
以下のサイトを参考にしました。ありがとうございました。
- atomutil - RubyでAtomPubを操作するパッケージをリリースしました - Codin’ In The Free World
- 徒然Blog | AtomAPI+Amebaブログ。
- アメブロ(Ameba/Ameblo) - ウェブサービスAPI
- アメブロにPHPで投稿してみました - アフィリエイトに疲れたくないクラシの処方箋
- 【続報】アメブロのAtomAPIを倒した « PHP « web « 脱オタクはぢめました
- 2.5.個人認証について|アメばた会議API
- 【iPhone SDK】アメーバブログなどにAtom APIを使ってアクセス: 趣味津々浦々
- アメブロへ楽天APIなどの情報を自動で投稿する | サラトガIT日記