まずはじめに、8/4にお亡くなりになったことが8/8に判明した俳優の津川雅彦氏、8/8にお亡くなりになった沖縄県知事の翁長雄志氏、両氏のご冥福をお祈りいたします。
で、こういう状況になったことを受け、当然というか何というか、Twitter政治界隈では両氏を肴に「ネトウヨは知事の死を喜ぶクズ!」「パヨクこそ津川さんの死を喜ぶクズ!」みたいな不毛極まる罵り合いをしている。
こういうことになるたび、私としては「どっちがクズかなんて、計量的に分析すればすぐ分かることなんじゃないか?」などと思っていたのと、久々にRubyで遊んでみたくなったので、自分なりに実際にやってみた。
分析対象
分析対象としたのは下記条件で取得できるツイート。ややこしい条件をつけると変なのしか取れなかったり面倒になりそうだと思ったので、シンプルな条件で取得することにした。
- 取得日時:2018/8/8 19:00 ~ 2018/8/9 19:00 の24時間が対象
- 取得条件:ツイート内容に「翁長」を含むものと「津川」を含むもの
- その他:リツイートは取得対象としない
データ抽出及び分析の方法
利用したソースコード及びコマンド
Qiitaの下記ソースをもとに、自分のやり方に合わせてアレンジした。
取得用ソースコード
#!/bin/env ruby #encoding:UTF-8 require "twitter" # アプリケーションキー(consumer key/secret)の読み込み # OAuth アクセストークンの読み込み @client = Twitter::REST::Client.new do | cnf | cnf.consumer_key = "XXXXXXXXXXXXXXX" cnf.consumer_secret = "XXXXXXXXXXXXXXX" cnf.access_token = "XXXXXXXXXXXXXXX" cnf.access_token_secret = "XXXXXXXXXXXXXXX" end # 変数の初期化 max_id = 0 counter = 0 # 無限ループ while counter == 0 do begin # 引数で受け取ったワードを元に、検索結果を取得(並びはデフォルトの新しい順)。 # ※最初はmax_id=0であるため、tweet ID 0以降のTweetから最古のもの上位100件を取得 @client.search(ARGV[0], count: 100, result_type: "recent", max_id: max_id).take(100).collect do |tweet| # Tweet ID, ユーザ名、Tweet本文、投稿日などなど・・・を1件づつ表示 print tweet.id print "," print tweet.user.id print "," print tweet.user.screen_name print "," print tweet.user.description.gsub(/(\r\n|\r|\n|\f|\t|\v|,)/,"") print "," print tweet.user.location.gsub(/(\r\n|\r|\n|\f|\t|\v|,)/,"") print "," print tweet.text.gsub(/(\r\n|\r|\n|\f|\t|\v|,)/,"") print "," print tweet.retweet_count print "," print tweet.favorite_count print "," print tweet.geo print "," print tweet.place print "," print tweet.source print "," print tweet.created_at print("\n") # 取得したTweet idをmax_idに格納 # ※新しいものから古いもの順(Tweet IDの降順)に表示されるため、 # 最終的に、取得した結果の内の最古のTweet IDが格納され、 # 次はこのID以降のTweetが取得される max_id = tweet.id - 1 end # 検索ワードで Tweet を取得できなかった場合の例外処理 rescue Twitter::Error::ClientError # 60秒待機し、リトライ sleep(60) retry end sleep(60) end
実行コマンド
ruby Twitter_KeywordSearch1.rb "翁長 since:2018-08-08_19:00:00_JST until:2018-08-09_19:00:00_JST exclude:retweets" > onaga.csv ruby Twitter_KeywordSearch2.rb "津川 since:2018-08-08_19:00:00_JST until:2018-08-09_19:00:00_JST exclude:retweets" > tsugawa.csv
はい、取得用ソースコード、見ての通り超冗長で雑なソースであります。 カンマ区切りにしているのはあとで分析用にそのほうが都合が良い(Excelでゴニョゴニョする)為。
仕様
まず実行コマンドで8/8 19:00 ~ 8/9 19:00を指定し、その範囲だけ検索する。ただし、ツイート検索用APIの仕様上、1回に取得できるのは100件までである。そのため、新しい(8/9 19:00寄りの)ツイートから100件とったら次は101件目から100件取得する、というのを8/8 19:00に到達するまで、1分間隔で何度も実行することで、全ツイートを取得するという仕様とした。
次の100件を取得するまで1分間隔を開けている理由は、ツイート検索用APIの制限で、15分間に可能なリクエスト数が180回に制限されているためである。
(もちろんもっと回数を増やすことは可能だが、あまり制限ギリギリの回数リクエストをかけていると垢BANされる気がしたので、元のソースから回数を変えることはしなかった)
抽出したデータ及びその分析方法
データ
取得したデータは下記の通り。
ファイル名 | 用途 |
onaga.csv |
翁長分析用生データ |
onaga(分析用).xlsx | 翁長分析の際に見やすいように、下記加工を施したデータ。 ・取得できた作成日時をJSTに変換した列を追加 ・フォーマットが崩れるツイートを除外(2件) |
onaga(分析用_サンプル).xlsx | onaga(分析用)全体を6等分し、分割した先頭100件を取得し、600件サンプル抽出したもの。 |
tsugawa.csv |
津川分析用生データ |
tsugawa(分析用).xlsx | 津川分析の際に見やすいように、下記加工を施したデータ。 ・取得できた作成日時をJSTに変換した列を追加 |
tsugawa(分析用_サンプル).xlsx | tsugawa(分析用)全体を6等分し、分割した先頭100件を取得し、600件サンプル抽出したもの。 |
取得位置.xlsx | 翁長、津川、両方のサンプル抽出時に、どの行からどの行まで取得したのかを示すファイル。 |
分析方法
分析方法としては、翁長、津川両方のサンプルファイルを下記の観点から目検で確認し、ネトウヨによる翁長への侮辱、あるいはパヨクによる津川への侮辱が、全書き込み中どのくらいのボリュームであったのか比較した。
- 相手が思想的にどのような陣営に所属するのか断定する書き込み(「津川はネトウヨ」や「翁長はクソサヨ」など)
- 相手が死んだことを喜ぶ書き込み
- 相手が死んだことで、何かが良くなるという内容の書き込み(「翁長が死んだことで、沖縄の政治が正常化する」など)
分析結果
えー、では、どちらがよりクズだったのか発表します。
翁長への侮辱:20個
津川への侮辱:19個
ほぼ同数でやんの……。
これで計量的によくわかった。要はどんな陣営にも一定程度の割合で屑がいるということ、そしてその割合は精々全書き込み中の3.3%程度に過ぎないということだ。
そして、書き込みを目検で追って思ったのが、翁長津川両氏に対する侮辱の書き込みより、相手陣営に対して「ネトウヨが翁長さんのことを悪く言った!」だの「サヨクが津川さんを侮辱している!」だのといった書き込みのほうが遥かに多いということだ。皆さん一体どこにいる藁人形に釘を打ち付けているんだろうか……?
まあ、嘘だと思うなら、私がUPしたファイルを皆さんも一緒に分析しては如何だろうか? 最終的な選り分けは結局主観に頼るものだったので偏っている可能性があるし、自分の分析方法が間違っている可能性も十分ある。
以上、分析結果でした。