このままでいいか

アニメとか,プログラミングとか,研究とか,思ったことをだらだらと書く感じで

CommonLispでAPIを使わずにTwitterのフォロワー数を取得してみた!

tomabuです.

最近CommonLispでいろんなデータの取得を試みています.

今回はその中の一つ,Twitterのフォロワー数を取得するプログラムについて書こうと思います.

動機

初めの動機は上述の通り,CommonLispでデータ収集することです. アニメの公式Twitterのフォロワー数とかを調べたかったのでやっちゃいました.

もしかすると読者の方が疑問に思っているのは,「なぜAPIを使わずに」なのかということかもしれません.

TwitterAPIを利用して開発をしたことがある方は,APIを叩きすぎて上限に達してしまったことがあるのでは無いでしょうか?

僕はなりました(笑) (※こちらのページで上限回数が調べられるようです.)

上限を無視できるように,各アカウントのTwitterのページのHTMLから直接フォロワー数を取得すればいいんじゃね?と思い至ったわけです.

もっと賢いやり方があるだろ,とか,意味あんのか?とか感じるかもしれませんがご容赦をm( )m

まさに素人考えですがとりあえずやってみました.

依存ライブラリ

今回使用するライブラリは,「closure-html」,「drakma」の2つです.

drakmaは言わずと知れたHTMLクライアントですね. closure-htmlはCommonLispで書かれたHTMLパーサです. drakmaで取得したHTMLソースをCommonLispで使いやすいようにリスト形式に直します.

Quicklispから簡単に使えるように公開してくれています. とても便利ですありがとうございます!

方法

Twitterのフォロワー数はHTMLソースの中のID"init-id",class"json-data"であるinputタグの値であるJSONデータの中のfollowers_countキーの値として設定されているようです.

また同JSONデータ内でフォロワー数の次にくるデータは,フォロー数であるfriends_countです. "followers_count"という文字列が出てきた場所から,"friends_count"という文字列が出てくるまでの間の文字列を取得するという方法を取ります.

まぁそのままですね.

コード

結果的にできたコードがコレです.

(ql:quickload '(closure-html drakma))
(defun get-twitter-follower (account-name)
  (let ((error-handle-count)
    (doing
      (ignore-errors
       (let ((twitter-html (princ-to-string
                (chtml:parse
                 (drakma:http-request
                  (concatenate 'string "https://twitter.com/" account-name))
                 (chtml:make-lhtml-builder)))))     
         (subseq twitter-html
             (+ 17 (search "followers_count" twitter-html))
             (- (search "friends_count" twitter-html) 2))))))
    (setf error-handle-count (length doing))
    (if (= 0 error-handle-count)
    "不明"
    doing)))

パット見余計な部分があります.エラーハンドラの部分です.(他にも余計なコードが有るとか,処理ミスってるとかは置いておきます)

普通に見れば

(let ((twitter-html (princ-to-string
                (chtml:parse
                 (drakma:http-request
                  (concatenate 'string "https://twitter.com/" account-name))
                 (chtml:make-lhtml-builder)))))     
         (subseq twitter-html
             (+ 17 (search "followers_count" twitter-html))
             (- (search "friends_count" twitter-html) 2))))))

この部分だけで目的の処理は完了していますし,殆どの場合に実行できます.

ですがいくつかのアカウント名に対してはエラーを返してしまい,実行できません.この原因は何なのか.恥ずかしながらイマイチわかりませんでした(^^;)

なのでエラーが返ってきたら"不明”という文字列を返すようにしました. エラーハンドリングについても正しいやり方が間違っているかもしれませんがとりあえず応急処置です.

実行が成功すれば,文字列でフォロワー数が返ってきます.

アニメ「ニセコイ」のTwitterアカウントを例に,実際に実行すると以下のようになります.(2016年6月18日)

f:id:dbym4820:20160618215822p:plain

ニセコイ公式アカウント f:id:dbym4820:20160618220016p:plain

どうやら正しい値が取れていますね. だから何?って話ですけど(笑)

結論

まぁなんだかんだでやりたかったことができました.

決して賢いやり方とはいえませんがなんとなく使えそうな気もしなくもないかもしれません(笑)

ツッコミお待ちしております.