🔙 Back to Top

Sat Jan 23 23:11:42 JST 2016

Twitter, あるツイートへのメンション (リプライ) を取得する

https://twitter.com/:screen_name/status/:id で表現されるような、 あるツイートへのメンション一覧を取得するためのツイートを取得するためのAPIは現在公開されていない.

事実として、公式サイトで出来る全てのことがAPIとして公開されているわけではない. 最近始まったPollに関するAPIもまだ出てないしね.

少し古いサイトだが、本当に無いっぽいのである:

少し関連して、自分でないあるユーザーへのメンション一覧というのも、同様にAPIとして公開されていない

ある事情でそのようなことをする必要が生じたので、

これを代替に用いて再現した. つまり、普通のTwitter検索でもって、"@sceen_name" で検索し、 該当するツイートへのメンションらしきものだけをフィルタするのである.

ソースコード (Ruby)

Rubyで書いた. これを見て真似しようとする人間はおそらくいないが、 そして大変恐縮だが、Twitter API を叩くのには twurl を用いている. 外部コマンドとして叩くだけである.

require 'json'

screen_name = "screen_name" # @screen_name
opt = ""

loop do
  res = JSON.parse `twurl '/1.1/search/tweets.json?q=@#{screen_name}&count=99&result_type=recent#{opt}'`
  tws = res["statuses"]

  for tw in tws
    if tw["in_reply_to_status_id_str"] == "684966772810776576" # リプライ先
      text = tw["text"].gsub("\n", " ")
      id = tw["id_str"]
      puts "#{id}: #{text}"
    end
  end

  next_id = tws[-1]["id_str"].to_i - 1
  opt = "&max_id=#{next_id}"
end

出力を log として保存する.

実際には、この検索で得た中で最近のツイートのidを持っておいた上で、 何度も同じ検索結果を得ないようにして、5分おきに上のスクリプトを走らせる. ただしそれでも同じ検索結果を得ないわけでもないので、

cat log | sort -nru -k1,1 > a && mv a log

などとして、idによって重複を取り除く.

余談

よく、Twitterを利用したキャンペーンで、 「リプライしてくれた人の中から抽選で何人にナニナニが当選します」 みたいなのがある. そういうのがあった. 21個の商品があり、 そのうち一つを選んだ上でリプライを送ると、 各商品につき一人ずつ当選する何かがあった. (リンクはしないが https://twitter.com/wanimagazine/status/684966772810776576 であった.)

「これ、締め切りギリギリまで待って、一番人気がないのを選べばいいんじゃない?」 と誰かがツイートしていたのを見て、 自動的に統計を取ることをした.

おおよその傾向を見るのに、上のスクリプトは役だった. 実のところ、ちゃんと in_reply_to を付けずにツイートしてあるのもちらほらと見かけたので、 その if 文は外して全部チェックした. ただし商品 (というかエロ漫画) を選ぶ方法としては、通し番号などは用いられず、 漫画のタイトルまたは作者をツイート本文に含める方法が取られていた. 誤字もあったし、そういったことにも寛容だと仮定して、 (たかだか21個だったので) ルールを手で愛情を込めて正規表現として書いた.

Twitter検索というのは、漏れが発生しやすい. しかしながら、結果が1件と2件とでは大きく違う. (例えば100件と101件とならそこまで違いはないが.) 理由はわからないけれど、全てのツイートがちゃんとデータベースに乗るわけではないらしいのだ. これは実際問題だった. 解決はしていない.

   cat list
\(なぱた\|ぱんでもにうむ\)
\(mogg\|肉体コミュニケーション\)
\(utu\|色は匂へど\)
\(ReDrop\|ヘンカノ\)
\(縁山\|める子\)
\(スミヤ\|センテンス\|ガール\)
\(無望菜志\|NTR\)
\(くじら\|ぐじら\|ギャルとかビッチとか色々\)
\(あきのそら\|じゅんれん\)
\(かるま\|龍狼\|淫ママ\)
\(狼亮輔\|求愛\)
\(DISTANCE\|あねこもり\)
\(ぴょん吉\|ぷにかの\)
\(小川ひだり\|ちちんくりくり\)
\(いーむす\|ヌレスジ\)
\(レオパルド\|スケッチ\)
\(ちょびぺろ\|はつもの果実\)
\(モチ\|死なず\|姫君\)
\(七宮つぐ\|あいまいますく\)
\(発情メソッド\|アシオミマサト\)
\(篠塚\|ファーストタッチ\)
   cat stat.sh
#!/bin/bash
for kw in `cat list`; do
  echo "<tr><td>$kw</td><td>" >>$OUT
  grep -i $kw log | wc -l  >>$OUT
  echo "</td></tr>" >>$OUT
done

上のリストで網羅できてない可能性がある. どのキーワードにも引っかからないツイートを次で抽出して、目視する. (問題は無かった.)

cp log rest
for kw in `cat list`; do
  cat rest | grep -v $kw > a
  mv a rest
done

最終的な結果は次.

PATTERN tweet数
(なぱた|ぱんでもにうむ) 121
(mogg|肉体コミュニケーション) 12
(utu|色は匂へど) 13
(ReDrop|ヘンカノ) 7
(縁山|める子) 7
(スミヤ|センテンス|ガール) 10
(無望菜志|NTR) 4
(くじら|ぐじら|ギャルとかビッチとか色々) 13
(あきのそら|じゅんれん) 25
(かるま|龍狼|淫ママ) 4
(狼亮輔|求愛) 4
(DISTANCE|あねこもり) 3
(ぴょん吉|ぷにかの) 46
(小川ひだり|ちちんくりくり) 3
(いーむす|ヌレスジ) 7
(レオパルド|スケッチ) 8
(ちょびぺろ|はつもの果実) 11
(モチ|死なず|姫君) 51
(七宮つぐ|あいまいますく) 70
(発情メソッド|アシオミマサト) 11
(篠塚|ファーストタッチ) 24

人気がはっきり分かって面白い. 雑誌の人気アンケートがここで公開されたようなものだ. 一番人気の無いものを選んで、2つのアカウントで応募した. 1/2の確率で少なくとも1つは当選する計算だったが、残念ながら外れた.

2つアカウントがあったので、一番少ないのに2つとも応募するか、 あるいは一番少ないものと二番目に少ないものに1つずつ応募する方法の二通りあった. どっちが有利になるかは、大体直感通りである:

一番少ないツイートをN件、二番目をM件とすると、

  1. N=M ならひとつずつ応募して(N+1)、(M+1)件にするのがよくて
  2. N+1=M ならどっちでも同じで、
  3. N+1<Mなら、Nの方に2つ突っ込むのが有利.