cucumber flesh

Rを中心としたデータ分析・統計解析らへんの話題をしていくだけ

🐣esa.ioをもっと好きになるためにesa.ioのAPIをRで使えるようにする

昨年の11月からesa.ioのアカウントを作って、チームではなくて個人の作業メモとして使っていた。といっても最初の1週間でほとんど使わなくなってしまい、2ヶ月の無料試用の期限が近づいてきてしまった。さてこのままフリートライアルでやめてしまうのももったいないような気がして、esa.ioを使い続けるためにRからesa.ioを操作できるようになれば良いような気がしてAPIを触ってみた、という記事(APIラッパーパッケージを作成する勉強をかねて、そのうちパッケージ化したい見よう見まねで作成した。まだすべてのAPIをカバーしているわけではないし、ドキュメントやテストも不足している...)。

f:id:u_ribo:20160119234513p:plain

先に完成したものの画像。Rmdでテンプレートを作れば、esa.ioでのテンプレート同様のものが作れる。

🐣 パッケージ化以前

APIの操作だけなので {httr}パッケージを使えば大体のことができてしまう。

library(httr)

使用するのはesa API v1。アクセストークンをURIクエリに含めることもできるが、リクエストヘッダに指定しておく方が便利なのでSys.setenv("ESA_IO_TOKEN" = "<token>")なりなんなりしておく。

# APIへの接続テスト
#   ステータスコード 200が返ってきていることを確認
GET("http://api.esa.io",
          path   = "/v1/teams",
          config = httr::add_headers(`Authorization` = paste("Bearer", Sys.getenv("ESA_IO_TOKEN")),
                                     `Content-Type`  = "application/json")) %>% 
  status_code()
## [1] 200

こんな感じで利用したいAPIメソッドとパラメータを指定した関数を実行する。今回利用したいのは「記事の一覧取得」「投稿の取得」「記事の作成」「記事の編集」「記事の削除」の5つ

リクエストヘッダの作成を都度やるのが面倒なのでrequestオブジェクトとして保存しておく。

headers <- httr::add_headers(`Authorization` = paste("Bearer", Sys.getenv("ESA_IO_TOKEN")),
                             `Content-Type`  = "application/json")

またAPIを叩くときにチーム名も必要なパラメータなので、オブジェクトにしておくと良い。

# 適宜変更
team_name <- "<team name>"

準備はこれで終い。早速利用するAPIを叩いてみる。

# 記事の一覧取得... https://docs.esa.io/posts/102#7-1-0
res_back <- GET("http://api.esa.io",
           path = paste("v1/teams", team_name, "posts", sep = "/"),
           config = headers) %>% content()

{purrr}パッケージを使ってごにょごにょするのも良いかもしれない。

res_back$posts %>% purrr::map_df(~ .[c("number", "name", "wip", "updated_at")]) %>% 
  head(3) %>% 
  knitr::kable(format = "markdown")
number name wip updated_at
18 Post Rmarkdown file TRUE 2016-01-19T22:25:42+09:00
17 tttt TRUE 2016-01-19T21:39:25+09:00
15 {httr}パッケージを使ってesa API経由で記事を投稿するテスト TRUE 2016-01-19T14:52:15+09:00
# 投稿の取得... https://docs.esa.io/posts/102#7-2-0
post_num <- 15
res_back <- GET("http://api.esa.io",
           path = paste("v1/teams", team_name, "posts", post_num, sep = "/"),
           config = headers) %>% content()
# 記事の作成... https://docs.esa.io/posts/102#7-3-0
POST("https://api.esa.io",
     path = paste("v1/teams", team_name, "posts", sep = "/"),
     config = headers,
     body = list(name    = "{httr}パッケージを使ってesa API経由で記事を投稿するテスト",
                 body_md = "ほげほげ",
                 wip     = TRUE,
                 tags    = array("sandbox")),
     encode = "json")

記事の編集はPATCHメソッドを利用すれば良いが、そのまま使うと前にあったテキストがなくなってしまう。以前のテキストも残すためには一度「投稿の取得」でやったように記事の内容を取得しておく必要があるっぽかった。

# 記事の編集... https://docs.esa.io/posts/102#7-4-0
PATCH("https://api.esa.io",
      path = paste("v1/teams", team_name, "posts", post_num, sep = "/"),
      config = headers,
      body = list(body_md = paste("これでどうでしょ", res_back$body_md, sep = "\n"),
                  original_revision = list(body_md = res_back$body_md,
                                           user = res_back$updated_by$screen_name)),
      encode = "json")
# 記事の削除... https://docs.esa.io/posts/102#7-5-0
DELETE("https://api.esa.io",
       path = paste("v1/teams", team_name, "posts", post_num, sep = "/"),
       config = header)

🐔 パッケージ化

上記の一連の処理を簡単にできるようにパッケージ化した。

github.com

githubinstall::install_github_package("uribo/esa.io")
library(esa.io)

またAPIからはテンプレートを利用できないが、Rmdでテンプレートを作成しておいて、ramrkdown::render()して生成したmdファイルをPOSTすれば良いかな、という感じなので、テンプレートを含んだパッケージを作成した。このことでRStudioで作ったRmdファイルをRの実行コードをつけたmdファイルに変換したファイルをesa.ioに記事としてあげることが可能になった。

create_rmd_post(team_name, 
                file = "160119_esa_io_httr.Rmd", 
                post_name = paste(emoji("hatched_chick"), "esa.ioをもっと好きになるためにesa.ioのAPIをRで使えるようにする"))

このcreate_rmd_post()関数で投稿した記事はこんな感じで表示される。...ちょっとだけesa.ioに投稿してからブログの方で追記があったので完全ではない。

esa-pages.io

🍵 所感

正直、 {httr}パッケージの使い方とかウェブAPIについての理解が足りなかったので既存のAPIラッパーパッケージを参考にしまくった。特に {qiitar}{estatapi}ソースコードを公開してくださっている id:yutannihilation さんには圧倒的感謝。