読者です 読者をやめる 読者になる 読者になる

TwitterのAPIドキュメントをスクレイピングしてRのパッケージを自動生成する

R

というやり方でパッケージをつくってみました。まだエラーが残ってますが、たぶんある程度は動くはずです。

Rのコードを生成するRのコードはこちらです。

twihttr/generate_R_code.R at master · yutannihilation/twihttr · GitHub

あんまり大したことはしてないんですが、やったことを軽くメモ。もっといいやり方あればだれか教えてください…

DSLっぽいやつ

Rのオブジェクト → Rのコードを生成する、という感じなので、これはDSLってことでは?と思ってAdvanced Rに書いてあるのを思い出しながらやってみました。でもたぶん大してDSLじゃないんですけど。

こんな感じのS3関数を用意しとくと、

library(stringr)

as.document <- function(x) UseMethod("as.document")

as.document.default <- function(x) {
  sprintf("#' %s\n", x)
}

as.document.param <- function(x) {
  indent <- 6
  width <- 100

  text <- unlist(str_split(str_wrap(x$description, width = 100), "\n"))
  text <- paste0("#'", str_pad("", indent), text)
  text  <- c(paste("#'", "@param", x$name), text)
  paste0(text, collapse = "\n")
}

as.document.list <- function(x) {
  paste(map_chr(x, as.document), collapse = "\n")
}

こんな感じのparamというSS3クラスをうまくドキュメントに変換できるようになります。

param1 <- structure(list(name = "param1", is_mandatory = TRUE, description = "This is a param"), class = "param")
param2 <- structure(list(name = "param2", is_mandatory = FALSE, description = "This is a optional param with very very very very very long explanation. This is a param. This is the only param we need. This is it."), class = "param")

cat(as.document(param1))
#> #' @param param1
#> #'      This is a param

cat(as.document(list(param1, param2)))
#> #' @param param1
#> #'      This is a param
#> #' @param param2
#> #'      This is a optional param with very very very very very long explanation. This is a param. This is
#> #'      the only param we need. This is it.

まあでも今回のはそんなネストしまくってるというわけではないので、果たして楽になったのかというとよく分かりませんでした。うーん。

formatR

Yihui氏のパッケージ。自動生成したコードのフォーマットを整えるために使いました。なんか他にもあった気がしたんですが、とりあえずこれがいちばん先に出てきたのでこれにしました。

こんな感じで使えます。

formatR::tidy_source(text = "a <- function(X) {if(X == 'TEST') {1} else {2}}")
#> a <- function(X) {
#>     if (X == "TEST") {
#>         1
#>     } else {
#>         2
#>     }
#> }

httrのローカルキャッシュ

httrはOAuthアプリをつくるとtokenをローカルにキャッシュします。が、毎回keyを求められてめんどくさいです。

この情報は.httr-oauthというファイルに入っているんですが、readRDS()で読むことができます。中にはハッシュとトークンのlistが入っていますが、appTwitterのものを使っておけば十中八九間違いないでしょう。

という感じのコードがこちらです。

load_cached_token <- function() {
  if(!file.exists(".httr-oauth")) return(NULL)
  oauth_cache <- readRDS(".httr-oauth")

  candidates <- oauth_cache %>%
    purrr::keep(~ is_twitter_app(.$app))

  if (length(candidates) == 0) {
    return(NULL)
  } else if(length(candidates) > 2) {
    stop("More than one twitter tokens are found. Remove .httr-oauth first!")
  }

  candidates[[1]]
}

is_twitter_app <- function(x) {
  !is.null(x) &&
  is(x) == "oauth_app" &&
    !is.null(x$app) &&
    x$app == "twitter"
}

感想

なんかもっと書くことある気がしたんですが、特にありません。けっこう細かいところでつまづいて疲れました。