窓際BLOG

プログラミングの学習メモや書籍の感想等を公開していきます。

Ruby:はてなブログAPIを使って記事の一覧をJSON形式で取得する

最近、技術系の記事はQiitaへの移行を考えているのですが、過去の記事の移行がめんどくさいなぁ。。。と思っていたので、記事の一覧をはてなブログAPIで取得するスクリプトを作ってみたので、その手順をメモしておきますφ(..)

ちなみに成果物は下記に公開してます。ソースコードだけ見たいという人は下記を、ご参照ください。

はてなブログAPIを使っての記事一覧をJSONで取得する · GitHub

やり方

APIKEYとルートエンドポイントを取得する

まずは、自分のブログにアクセスするためのAPIKEYとルートエンドポイントを取得します。それぞれの役割は下記の通りです。

名前 役割
APY KEY APIで自身のブログにアクセスする際のパスワード
ルートエンドポイント APIへRESTでアクセスする際に指定するURL

APIKEY及びルートエンドポイントは、自分のブログの詳細設定画面で確認することが出来ます。

https://blog.hatena.ne.jp/アカウント/ブログID.hatenablog.com/config/detail

f:id:madogiwa0124:20171210224903p:plain

記事を取得してみる

それでは、実際にはてなブログAPIを使って記事を取得していきます。
基本的な流れは下記の通りです。

  1. ルートエンドポイント/entryにGETリクエストを作成
  2. ベーシック認証でのアカウント情報をGETリクエストに付与
  3. GETリクエストを発行
  4. レスポンスボディに設定された記事を取得

実際のソースコードと解説は下記の通りです。

require 'uri'
require 'net/http'

# ルートエンドポイントからURLを生成
uri = URI(ROOT_END_POINT)
# GETリクエストを作成
req = Net::HTTP::Get.new(uri)
# ベーシック認証でアカウント情報を付与
req.basic_auth(USER_ID, APY_KEY)
# HTTPリクエストを送付
res = Net::HTTP.start(uri.host,
                      uri.port,
                      use_ssl: true) { |http| http.request(req) }
# 記事情報を取得(XML形式)
res.body

記事のタイトルと本文を取得する

取得結果からタイトルと本文といった特定部分を取得するためには、取得したXML形式の記事情報を解析する必要があります。
今回はNokogoriを使用してXMLを解析してタイトルと本文を取得しました。Nokogiriの説明は下記の記事にまとめておりますので、そちらを参照してください。

madogiwa0124.hatenablog.com

実際にレスポンスボディに設定される記事(XML形式)は下記のような形になります。

<entry>
  <id>tag:blog.hatena.ne.jp,2013:blog-madogiwa0124-6653812171402746641-8599973812325431185</id>
  <link rel="edit" href="https://blog.hatena.ne.jp/madogiwa0124/madogiwa0124.hatenablog.com/atom/entry/8599973812325431185"/>
  <link rel="alternate" type="text/html" href="http://madogiwa0124.hatenablog.com/entry/2017/12/10/232320"/>
  <author><name>madogiwa0124</name></author>
  <title>タイトル</title>
  <updated>2017-12-10T23:23:20+09:00</updated>
  <published>2017-12-10T23:23:20+09:00</published>
  <app:edited>2017-12-10T23:23:20+09:00</app:edited>
  <summary type="text">本文</summary>
  <content type="text/x-markdown">本文</content>
  <hatena:formatted-content type="text/html" xmlns:hatena="http://www.hatena.ne.jp/info/xmlns#">&lt;p&gt;本文&lt;/p&gt;</hatena:formatted-content>
  <app:control>
    <app:draft>no</app:draft>
  </app:control>
</entry>

そのため、entry配下のtitlecontentを取得するには下記のようなコードで行うことが出来ます。今回はタイトルと本文をHash形式で取得出来るようにしてみました。

# Nokogiriで取得したXMLをパース
entry = Nokogiri::XML.parse(res.body, nil, 'utf-8')
# タイトルの一覧を取得
titles = entry.css('entry title').map(&:text)
# 本文の一覧を取得
contents = entry.css('entry content').map(&:text)
# Hash形式でタイトルと本文のリストを作成
titles.length.times do |i|
  entry_hash_list << { title: titles[i], content: contents[i]}
end

全ての記事を取得する

はてなブログAPIでは、1回のレスポンスで10記事までしか返却出来ないため、全ての記事を取得するためには次の記事の一覧が取得出来るURLを取得し、リクエストを複数回送らないといけません。

次の記事の一覧へのURLは、レスポンスボディに下記のような形で設定されます。

<link rel="next" href="https://blog.hatena.ne.jp/madogiwa0124/madogiwa0124.hatenablog.com/atom/entry?page=1509279003" />

上記XMLを解析し、URL部分を取得するコードは下記の通りです。

# 次の記事一覧へのリンク部分を取得
link_urls = entry.css("link[rel^='next']")
# リンク部分からURLの文字列を取得※取得でいなかった場合はnil を設定
next_url = link_urls.empty? ? nil : link_urls.attribute('href').value

上記で取得したURLに再度記事を取得してみるで記載した処理を行えば、次の記事の一覧が取得することが出来るので、次のページのURLが取得出来なくなるまで処理を繰り返せば全ての記事を取得することが出来ます。

全ての記事のタイトル、本文、カテゴリをJSON形式で取得する

下記は私が作成したはてなブログAPIを使った記事のタイトル、本文、カテゴリを取得するスクリプトです。

gist.github.com

参考

はてなブログAtomPub - Hatena Developer Center

cartman0.hatenablog.com

以上です