LoginSignup
6
10

More than 5 years have passed since last update.

rvest で OAuth 認証してスクレイピング #rstatsj

Last updated at Posted at 2015-08-20

以前、こんな記事を書いた。

しかし最近は Twitter アカウントなどで OAuth を使ってログインできるサイトが増えてきた。
私も Qiita は Twitter ID を紐づけて OAuth でログインしている。

rvest を使って OAuth 認証するのは、上記記事のやり方にひと手間加える必要があるので、ここで紹介しよう。

Qiita に Twitter ID でログイン

例として、Qiita に Twitter ID でログインしてみる。

R
library(rvest)

# Qiita の Twitter 用認証ページ
login_page <- html_session("https://qiita.com/auth/twitter")

# 認証ページのログインフォームにアカウント名とパスワードを入れる
login_form <- html_form(login_page)[[1]] %>% 
  set_values(`session[username_or_email]`="hoxo_m", `session[password]`="****")

# Submit するとリダイレクトページが表示される
redirect_page <- submit_form(login_page, login_form)

まず、Qiita の Twitter 認証ページにアクセスする。
すると、Twitter 側の認証ページへリダイレクトされるので、そこでログインフォームにアカウント名とパスワードを入力する。
これを Submit すると、今度は Qiita 側へ認証情報を返すためにリダイレクトしようとするのだが、rvest では自動的に遷移しない。

したがって、この redirect_page ページから、認証情報を返すためのリンクを探してそのリンクをたどらなければならない。

R
redirect_page %>% html_node(xpath='//body')
結果
(省略)
<div id="bd" role="main">
  <div class="happy notice callback">
    <h2>アプリケーションに戻ります。しばらくお待ちください。</h2>
    <p>自動的に移動しない場合は<a class="maintain-context" href="https://qiita.com/auth/twitter/callback?oauth_token=***&amp;oauth_verifier=***">こちら</a>をクリックしてください</p>
  </div>
</div>
(省略)

この「自動的に移動しない場合はこちらをクリックしてください」というのが認証情報を返すためのリンクである。
このリンクを rvest でたどるには、次のようにする。

R
session <- redirect_page %>%
  follow_link(xpath = '//*[@id="bd"]/div/p/a')

以上で、Qiita に Twitter ID でログインしたセッションを作成することができた。

あとは通常どおり、ログインした状態でスクレイピングできる。

R
session %>% 
  jump_to("http://qiita.com") %>% 
  html_nodes(xpath='//div[@class="userInfo"]/div/div') %>%
  html_text
結果
[1] "hoxo_m"          "753Contribution"

hoxo_m アカウントでログインできていることが確認できた。

Qiita の通知情報をスクレイピング

ここからは完全に余談で、Qiita の通知一覧のページから、通知情報をスクレイピングしてみる。

R
library(lambdaR)
library(pforeach)

npforeach(i=1:99, .c=rbind)({
  url <- sprintf("http://qiita.com/notifications?page=%d", i)
  message(url)

  nodes <- session %>%
    jump_to(url) %>%
    html_nodes(xpath = '//div[@class="notification_actionWrapper"]')

  Sys.sleep(1)

  nodes %>%
    Map_(node: {
      action <- tryCatch({
        node %>% html_node(xpath='span[@class="action"]') %>% html_text
      }, error = f_(e: {
        # action が「編集」「投稿」の場合
        node %>% html_node(xpath='*/span[@class="action"]') %>% html_text
      }))
      if(action == "ツイート") {
        who <- ""
      } else {
        who <- node %>% html_node(xpath='span[@class="notification_user"]') %>% html_text
      }
      if(action %in% c("フォロー", "ツイート", "Thank!")) {
        url <- ""
      } else if(action %in% c("編集", "投稿")) {
        url <- node %>% html_node(xpath='a') %>% html_attr("href")      
      } else {
        url <- node %>% html_node(xpath='span[@class="action"]/a') %>% html_attr("href")
      }
      if(action == "フォロー") {
        title <- "あなた"
      } else if(action == "採用") {
        title <- "編集リクエスト"
      } else if(action == "Thank!") {
        title <- "あなたのコメント"
      } else {
        title <- node %>% html_node(xpath='span[@class="title"]') %>% html_text        
      }
      data.frame(who, action, title, url, stringsAsFactors = FALSE)
    }) %>%
    Reduce_(rbind)
}) -> result

knitr::kable(head(result))
who action title url
kisy ストック "rvest すげえ。#rstatsj" http://qiita.com/hoxo_m/items/264b45684fcb657cf285
garam ストック "read.table() でヘッダ..." http://qiita.com/hoxo_m/items/b77f1566d3a848e46c92
uri 編集 "【gifアニメつき】テキストエディ..." http://qiita.com/uri/items/a4a6e9abdbe9a913d657/revisions
uri 編集 "【gifアニメつき】テキストエディ..." http://qiita.com/uri/items/a4a6e9abdbe9a913d657/revisions
dichika メンション "readr::parse_date..." http://qiita.com/dichika/items/4255bc4b5949c9b367f1
ddintokyo ストック "RStudio Shiny チュー..." http://qiita.com/hoxo_m/items/c8365117f3444fb51df4

このデータから、ストック情報だけを取り出して、自分の記事をよくストックするユーザを見つけてみよう。

R
library(dplyr)

stock_ranking <- result %>%
  filter(action == "ストック") %>%
  count(who) %>%
  arrange(desc(n))

knitr::kable(head(stock_ranking, 20))
who n
HirofumiYashima 47
uri 39
Reds 32
ytakky 26
kasumani 19
cof 17
horihorio 16
P_tan 12
soogie 11
hiro_matsuno2 10
kaz-yos 10
st450 10
tktz 10
ginmaru 8
selious 8
wakuteka 8
R_beginner 7
hayashiyus 7
heliac2000 7
ksomemo 6

ここは @uri さんが一位であってほしかった。

Enjoy!

関連

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10