日々のつれづれ

不惑をむかえ戸惑いを隠せない男性の独り言

twitteRの仕様が変わった・その1

いつの間にかRのtwitteRパッケージも仕様変更していた
どうやら、ツイを取得するだけでもアプリ開発のIDが必要ということのようです
今更感もありますが、自分用にメモをとってみた

TwitterAPIが完全に1.1に移行したらしい

TwitterのDevelopersのページにはこんな記載が

Today, we are retiring API v1 and fully transitioning to API v1.1. Given the array of blackout tests, blog posts, Tweets and other updates, this should (hopefully) not be a surprise. Before I get into the slew of resources available for you, let me first say thank you for your cooperation over the last several months.

Based on the blackout tests and looking at the numbers, we can see that the vast majority of applications have transitioned to API v1.1. If you still have not updated your app and you want people to be able to continue using it, it’s not too late! Documentation is available here.

API v1 Retirement is Complete - Use API v1.1

既に、API1.1に移行しているアプリもあるからダメージは小さいのかもしれない
ソリューションビジネスには興味がないので、経営に影響があるのか、ないのか、まったくピンときませんが

OAuth認証の取得

まずは、TwitterのIDがあることが前提です
Twitterに登録した由緒正しき人にしかデータは渡しませんよ」ってことです

はじめにDevelopersのサイトにアクセスします

Developersに入るとアプリ登録ページになるので、アプリを登録します

そして、Detailタブの下にあるCreate my access tokenのボタンを押します
すると、OAuth toolタブに付随していくつかのIDが付与されていることが分かります

ここで大切なのは、次の4つです

  • Consumer key…Detailsタブにあります
  • Consumer secret…Detailsタブにあります
  • Access token…Detailsタブの下にあるCreate my access tokenのボタンを押すと作成されます
  • Access token secret…Detailsタブの下にあるCreate my access tokenのボタンを押すと作成されます

これをメモします
どれも個人に付与されているIDなので、他人に教えてはいけません

あと、Access levelはデフォルトがRead Onlyになっています
Rから操作することを考えると、変更しておいた方が便利と思います
Settingsタブの下にあるApplication typeをRead, Write and Access direct messagesに変更します(Updateを忘れずに)

これで、RでtwitteRパッケージを使う準備が整いました

Rで認証コードを入れる

twitterで登録した認証コードをR内で入力して、RからTwitter側へアクセスします

> library("twitteR")
 要求されたパッケージ ROAuth をロード中です 
 要求されたパッケージ RCurl をロード中です 
 要求されたパッケージ bitops をロード中です 
 要求されたパッケージ digest をロード中です 
 要求されたパッケージ rjson をロード中です 

> #メモしたIDのオブジェクト
> cKey <- Consumer keyの文字列
> cSec <- Consumer secretの文字列
> aTok <- Access tokenの文字列
> aSeq <- Access token secretの文字列
> reqURL <- "https://twitter.com/(ここにTwitter IDを入れる)/"
> aURL <- paste("https://api.twitter.com/oauth/", aTok, sep="")
>
> # Oauthの認証を得る
> twi <- OAuthFactory$new(handshakeComplete=TRUE,
+                         signMethod="HMAC",
+                         consumerKey=cKey,
+                         consumerSecret=cSec,
+                         oauthKey=aTok,
+                         oauthSecret=aSeq)
> 
> registerTwitterOAuth(twi)
[1] TRUE

handshakeCompleteはTwitter APIとしてアクセスをするための引数で、signMethodは入力の方式のようですが、詳しいことは知りません
でも、これでTwitter側がアプリ開発のためのアクセスと認めてくれたことになります

tweetを取得する(userTimeline)

後は検索するための文字列を入力すればツイを取得できます
引数userでtwitter IDを入力すると、取得できます
引数nで取得するtweetの数を設定できますが、Twitterの仕様上、上限は3200です

> x <- userTimeline(user="tweetfromr")
> x
[[1]]
[1] "tweetfromr: 2回目のtweetになります。こんなコメントをネットに流しています。"
[[2]]
[1] "tweetfromr: RからTwitterを使うパッケージはtwitteRといいます。Rは大文字Rを入れたパッケージが多いですね。"
> is(x)
[1] "list"   "vector"

返り値はリスト形式になっていて、各tweetがfavされた、RTされた、リプされたとかの情報を持ちます

> str(x[[1]])
Reference class 'status' [package "twitteR"] with 14 fields
 $ text        : chr "2回目のtweetになります。こんなコメントをネットに流しています。"
 $ favorited   : logi FALSE
 $ replyToSN   : chr(0) 
 $ created     : POSIXct[1:1], format: "2013-06-15 14:07:00"
 $ truncated   : logi FALSE
 $ replyToSID  : chr(0) 
 $ id          : chr "345905281873620992"
 $ replyToUID  : chr(0) 
 $ statusSource: chr "web"
 $ screenName  : chr "tweetfromr"
 $ retweetCount: num 0
 $ retweeted   : logi FALSE
 $ longitude   : chr(0) 
 $ latitude    : chr(0) 
 and 42 methods, of which 30 are possibly relevant:
   getCreated, getFavorited, getId, getLatitude, getLongitude, getReplyToSID,
   getReplyToSN, getReplyToUID, getRetweetCount, getRetweeted, getScreenName,
   getStatusSource, getText, getTruncated, initialize, setCreated,
   setFavorited, setId, setLatitude, setLongitude, setReplyToSID, setReplyToSN,
   setReplyToUID, setRetweetCount, setRetweeted, setScreenName,
   setStatusSource, setText, setTruncated, toDataFrame

最後に並んでいる"and 42 methods, of which 30 are possibly relevant"以下の文字列はlistのそれぞれの要素を取り出す関数です

#tweetした日時を取り出す:getCreated()
> lapply(x, function(i) i$getCreated())
[[1]]
[1] "2013-06-15 14:07:00 UTC"
[[2]]
[1] "2013-06-15 13:26:37 UTC"

#tweetのIDを取り出す:getId()
> lapply(x, function(i) i$getId())
[[1]]
[1] "345905281873620992"
[[2]]
[1] "345895119616110593"

#tweetしたクライアントを取り出す:getstatusSource()
> lapply(x, function(i) i$getStatusSource())
[[1]]
[1] "web"
[[2]]
[1] "web"

トレンドを取得する(getTrends)

トレンドは国と地域で異なります
まず、どこのトレンドが欲しいか決めないといけません

> aTL <- availableTrendLocations()
> head(aTL)
            name country woeid
1         世界中             1
2     ウィニペグ  カナダ  2972
3         オタワ  カナダ  3369
4     ケベック州  カナダ  3444
5 モントリオール  カナダ  3534
6       トロント  カナダ  4118
> is(aTL)
[1] "data.frame" "list"       "oldClass"   "vector"    

返り値がdata.frameなのでcountryで日本を指定してみます

> subset(aTL, subset=country=="日本")
          name country    woeid
183     北九州    日本  1110809
184       埼玉    日本  1116753
185       千葉    日本  1117034
186       福岡    日本  1117099
187  Hamamatsu    日本  1117155
188       広島    日本  1117227
189       川崎    日本  1117502
190       神戸    日本  1117545
191       熊本    日本  1117605
192     名古屋    日本  1117817
193       新潟    日本  1117881
194 Sagamihara    日本  1118072
195       札幌    日本  1118108
196       仙台    日本  1118129
197       高松    日本  1118285
198       東京    日本  1118370
199       横浜    日本  1118550
302       沖縄    日本  2345896
368       大阪    日本 15015370
369       京都    日本 15015372
389       日本    日本 23424856
415       岡山    日本 90036018

地域がnameで指定できるので横浜を指定します
国と地域はwoeidで決まるので、日本の横浜は1118550です

> getTrends(woeid=1118550)
         name
1    #henneko
2      ライブ
3    頭大丈夫
4     #comcha
5     #anispa
6      注意報
7  コンフェデ
8      #sougo
9       #joqr
10 えりありー
                                                                         url
1                                     http://twitter.com/search?q=%23henneko
2                    http://twitter.com/search?q=%E3%83%A9%E3%82%A4%E3%83%96
3           http://twitter.com/search?q=%E9%A0%AD%E5%A4%A7%E4%B8%88%E5%A4%AB
4                                      http://twitter.com/search?q=%23comcha
5                                      http://twitter.com/search?q=%23anispa
6                    http://twitter.com/search?q=%E6%B3%A8%E6%84%8F%E5%A0%B1
7  http://twitter.com/search?q=%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A7%E3%83%87
8                                       http://twitter.com/search?q=%23sougo
9                                        http://twitter.com/search?q=%23joqr
10 http://twitter.com/search?q=%E3%81%88%E3%82%8A%E3%81%82%E3%82%8A%E3%83%BC
                                           query   woeid
1                                     %23henneko 1118550
2                    %E3%83%A9%E3%82%A4%E3%83%96 1118550
3           %E9%A0%AD%E5%A4%A7%E4%B8%88%E5%A4%AB 1118550
4                                      %23comcha 1118550
5                                      %23anispa 1118550
6                    %E6%B3%A8%E6%84%8F%E5%A0%B1 1118550
7  %E3%82%B3%E3%83%B3%E3%83%95%E3%82%A7%E3%83%87 1118550
8                                       %23sougo 1118550
9                                        %23joqr 1118550
10 %E3%81%88%E3%82%8A%E3%81%82%E3%82%8A%E3%83%BC 1118550

横浜では#hennekoのハッシュタグがトレンドのようですね

ハッシュタグを辿る(searchTwitter)

では、#hennekoのタグを見てみます

> sT <- searchTwitter(searchString="#henneko", n=1000)
> is(sT)
[1] "list"   "vector"

リストになっているので一覧にすると分かりにくそうですね

> sT[1:3]
[[1]]
[1] "S3t5S9t6: ktkr #henneko"
[[2]]
[1] "yuilock9: RT @seiyufan: 【画像】『変態王子と笑わない猫。』月子ちゃんの描き下ろし抱き枕カバーキタ━━━━━━(゚∀゚)━━━━━━! http://t.co/hXgBPxAuiW #henneko http://t.co/bKCzXCEVyk"
[[3]]
[1] "kakkakka_ka: #henneko"

やはり、分かりにくい
取得したtweetをdata.frameに変換する関数はtwListToDFです

> sTdf <- twListToDF(sT)
> str(sTdf)
'data.frame':	1000 obs. of  14 variables:
 $ text        : chr  "ktkr #henneko" "RT @seiyufan: 【画像】『変態王子と笑わない猫。』月子ちゃんの描き下ろし抱き枕カバーキタ━━━━━━(゚∀゚)━━━━━━! http://t.co"| __truncated__ "#henneko" "今回ヤヴァイw #henneko" ...
 $ favorited   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ replyToSN   : chr  NA NA NA NA ...
 $ created     : POSIXct, format: "2013-06-15 14:44:35" "2013-06-15 14:43:17" ...
 $ truncated   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ replyToSID  : chr  NA NA NA NA ...
 $ id          : chr  "345914741539106816" "345914414379180032" "345913799452266498" "345913468282617856" ...
 $ replyToUID  : chr  NA NA NA NA ...
 $ statusSource: chr  "web" "web" "<a href=\"http://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>" "web" ...
 $ screenName  : chr  "S3t5S9t6" "yuilock9" "kakkakka_ka" "S3t5S9t6" ...
 $ retweetCount: num  0 25 0 0 0 0 0 0 0 0 ...
 $ retweeted   : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ longitude   : logi  NA NA NA NA NA NA ...
 $ latitude    : logi  NA NA NA NA NA NA ...
> head(sTdf$"text")
[1] "ktkr #henneko"                                                                                [2] "RT @seiyufan: 【画像】『変態王子と笑わない猫。』月子ちゃんの描き下ろし抱き枕カバーキタ━━━━━━(゚∀゚)━━━━━━! http://t.co/hXgBPxAuiW #henneko http://t.co/bKCzXCEVyk"
[3] "#henneko"                                                                                 [4] "今回ヤヴァイw #henneko"                                                                                [5] "バーバラw #henneko"                                                                                  [6] "今週も月子かわいかったな #henneko"

どうやら#hennekoは『変態王子と笑わない猫。』というマンガ、アニメのようですね

Twitterクライアントを調べる

Tweet情報にはstatusSourceがあり、これはTweetが発信された端末情報が記載されています
これは上に書いたとおり、listからオブジェクトを取得するための関数が準備されています
statusSourceはhtmlフォーマットなので

> SS <- lapply(sT, function(i) i$getStatusSource())
> SS[1:3]
[[1]]
[1] "web"
[[2]]
[1] "web"
[[3]]
[1] "<a href=\"http://twitter.com/download/android\" rel=\"nofollow\">Twitter for Android</a>"
> ss <- sapply(SS, function(i) sub("<a.*>(.*)</a>", "\\1", i))
> head(ss)
[1] "web"                 "web"                 "Twitter for Android"
[4] "web"                 "Twitter for iPhone"  "Tweetbot for iOS"   
> ss <- table(ss)
> ss <- ss[order(ss, decreasing=TRUE)]
> pie(ss)


Janetterが多いですね
噂どおりの人気ですね

ちょっと思ったこと

セキュリティーを強めたのだと思いますが、自由度が高いことがウリのtwitterがセキュア対策に多くの労力を割いている現状は複雑ですね
これは、新しい機能開発に投資すべき原資を安全対策に投資しているってこと
もちろん、CSR意識の高い企業なら当たり前のことなんですが