0

Twitterの地名なうbotを全blockするOAuthアプリ

http://shokai.mag.keio.ac.jp/block_nowbots/から使える。
(8月15日:URL変更しました

とりあえずSinatraとOAuthの組み合わせを試してみたかったので、DBは使わないものを作りたかった。取得したOAuthのtokenなどはその場で捨てている。blockコマンドを送る権限だけを一時的に委譲してもらう。


以下技術的なことのメモ。
■OAuthアプリの登録
まずhttp://twitter.com/oauth_clientsでアプリを登録し、consumer keyとconsumer secretを取得する。
で、下のコード中のCONSUMER_KEY, CONSUMER_SECRETを書き換える。


■必要なライブラリ
必要なgemをインストールする。最新版にした。

sudo gem install oauth twitter sinatra
それぞれ0.3.5, 0.6.13, 0.9.4がインストールされた。
twitterは内部でoauthに依存していて、oauthはバージョン毎に関数がけっこう変わっている。このバージョンの組み合わせなら動く。


■動かす
そして起動。
ruby block-nowbots.rb -p 2692 -s mongrel
thinだと複数クライアントから同時にアクセスした時1クライアントずつしか対応してくれなかったんだけど、mongrelは全クライアントに同時に応答してくれた。mongrelにいつのまにかそういう機能がついたのか、sinatraのバグでthinがthread処理されないのかはよくわからない。
sinatraもrailsと同じくデプロイまわりを工夫した方がよさそう。passenger使うのがいいのかな?


参考:


block-nowbots.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
require 'oauth'
require 'twitter'

HOST_AND_PORT = "localhost:2692"

CONSUMER_KEY = "your-consumer-key"
CONSUMER_SECRET = "your-consumer-secret"

BOTS = 'nishinipporinow,nippori_now,kanda_now,tabata_now,sugamo_now,komagome_now,shinokubo_now,mejiro_now,takadanobabanow,okachimachi_now,uguisudani_now,ikebukuro_now,otsuka_now,akiba_now,tokyo_now,harajuku_now,shibuya_now,shibuya_now,yoyogi_now,shinjuku_now,ebisu_now'

set :sessions, true
def consumer
  OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET,
                      :site => "http://twitter.com")
end

template :layout do
  '<html>
     <body>
       <h1>地名なうbotを全blockするOAuthアプリ</h1>
       <%= yield %>
       <hr style="margin-top: 100px" />
       <a href="http://shokai.org">http://shokai.org</a><br /><a href="http://shokai.org/blog/archives/4698">解説</a>
     </body>
   </html>'
end

get '/' do
  @request_token = consumer.get_request_token(:oauth_callback => "http://#{HOST_AND_PORT}/auth")
  session[:request_token] = @request_token.token
  session[:request_token_secret] = @request_token.secret
  erb %{
    <p><%= BOTS %><br />をblock設定します</p>
    <p>OAuth認証してください</p>
    <a href="<%= @request_token.authorize_url %>">認証する!</a>
  }
end

get '/auth' do

  @request_token = OAuth::RequestToken.new(consumer,
                                          session[:request_token],
                                          session[:request_token_secret])
  @access_token = @request_token.get_access_token({},
                                                  :oauth_token => params[:oauth_token],
                                                  :oauth_verifier => params[:oauth_verifier])
  session[:access_token] = @access_token.token
  session[:access_token_secret] = @access_token.secret

  erb %{
    <p>認証成功</p>
    <p><a href="/block_now_bots">地名なうbotをblockする</a>(全部で<%= BOTS.split(",").size*3 %>秒くらいかかる)</p>
    <a href='/'>戻る</a>
  }
end

get '/block_now_bots' do
  oauth = Twitter::OAuth.new(CONSUMER_KEY, CONSUMER_SECRET)
  oauth.authorize_from_access(session[:access_token], session[:access_token_secret])
  twit = Twitter::Base.new(oauth)
  BOTS.split(",").each{|bot|
    twit.block(bot)
    puts "block #{bot}"
    sleep 3
  }
  erb %{
    <p>たぶんblockしました</p>
    <p><a href="http://twitter.com/yamanote_now/following">確認</a></p>
  }
end

0

buzztterでtimelineを作るYahoo Pipes

buzztter.comでtwitter上の最近の頻出単語の統計を出してくれている。
頻出語の上位5単語で検索してタイムラインを作るYahoo Pipesを作った。

Pipes: buzztter timeline

1週間ぐらい見ているが、だいたいみんなテレビとかゲームとか選挙とか芸能人の話題、眠気や月曜日出勤したくないなどの体調の問題を喋っている。ワイドショー的。
上位3語や10語も試したけど、5語ぐらいが話題がバラけすぎもせず偏りすぎもせずちょうどよかった。


前作「twitter上で親しい人のタイムラインを動的に生成するYahoo Pipes」は自分に近い人がでてくるけど、今度のはtwitterの中心近くで騒いでいる人たちが見える。

0

twitter上で親しい人のタイムラインを動的に生成するYahoo Pipes

修論を出した後のテンションでまたYahooPipesを作った。

Pipes: twitter dynamic timeline


親しい人で動的にタイムラインを作るpipes。
しくみは単純で、最近favを付けたり付けられたり、replyしたりされたりした相手でタイムラインを作る。
自分の発言内容やそれに対する相手の反応によってメンバーが動的に入れ替わる。

これの面白いのは、キーワードでの振り分けと異なりごく普通にtwitterを使っているだけでタイムラインが親しいメンツに変わっていく。
一見流動性が無いように見えるが、自分をふぁぼったりreplyしてきた人は入ってくるし、その人にreplyしたりfavし返せばしばらくはdynamic timelineに入り続ける。相手をfollowする必要すらない。

忙しくてtwitter見れない時は、これだけ見ておけば親しい人のpostはだいたいチェックできるかもしれない。


RSSにはusericons.relucks.orgを使ってアイコンを表示した。ユーザ名やURLもリンクになるようにしてある。
twitter dynamic timeline


pipes全体図
twitter dynamic timeline


一番上ですぐ分岐させて、左から順に

という具合。

YahooPipesは処理時間が長くなりすぎるか、pipesから相手へのアクセスが多くなりすぎるとエラーが出てしまう。

処理時間が長くならないようにするには並列化。pipeを縦につなげないようにする。
重要なのはpipesから外部サイトへのHTTPリクエストからレスポンスまでの時間だと思う。米yahooの強力なサーバーなので正規表現でページ解析する処理時間はたぶん無視していい。

今回上の方で4つに分けているように、早めにsplitモジュールで分けてそれぞれでHTTPリクエストを発行させてレスポンス待ちにすると速い。splitで分けられたそれぞれと、Loopモジュール内でFetch PageやFetch Feedモジュールは自動的にpipes内で非同期処理になってそうな気がする。
※この時どれかで取得した結果を他のsplit先に使おうとすると、結局縦に1本につなげているのと変わらなくなってしまうので注意しましょう

pipesから他のサイトへのアクセスについては、twitterとyahooが地理的に遠くないからなのか制限が緩くなっているのかよくわからないが、3秒で100アクセスぐらいしてるのにエラーはでない。

0

ahokaiに適当にtimelineの空気を読んで発言する機能、NGワード機能を追加、gemのアップデートに対応など


ahokaiという、俺の発言を収集・再構築して喋るtwitter botに

  • ruby twitter gem0.6あたりから認証方法が変わったので、現最新版(0.6.6)に対応
  • タイムラインに含まれる名詞の出現回数をチェックしてその単語から文章を作る
  • post前に発言を検閲し、NGワードが含まれていたら発言を再度作り直す
という機能追加を行った。
あとは、replyとNGユーザ機能を気の向いた時に付ける予定。


ahokaiについては橋本商会 スーパーボット大戦およびymrl.net – 裏Twitterへ。
勝手にbot化しても許してくれそうな人の発言を収集し、賛同者?の方々と共にすこしずつbotが増やしています。ありがとうございます。


■既にahokaiを動かしていて、バージョンアップしたい場合
http://bitbucket.org/shokai/bot-ahokai/ からhg pullしてhg upするか、*.rbファイルを最新版のソースコードに置き換えてください。
DBやconfig.yaml等は書き換えなくても動作します。
ruby twitter gemはアップデートして最新のものを使わなければ動きません

sudo gem update twitter –remote

windowsの場合はsudoはいりません。


—–(ここから下の機能は、設定しなくても今まで通り動くので面倒ならやらなくて良い)—–


■ruby twitter gemの認証方法の変更への対応
コンストラクタに渡す引数が変わってた → twitter gemのHTTPAuth – 橋本詳解


■タイムラインに含まれる名詞の出現回数をチェックしてその単語から文章を作る
Buzzwords.rbに実装した。
timelineをMeCabで名詞だけ抽出して、出現回数をチェックして適当に名詞を選びそこから左右にマルコフ連鎖を伸ばす。
以前実装したbuzztterのRSSから発言を作る機能を拡張したので一瞬で完成した。

config.yamlのbuzzratioという項目で頻度が設定できます。sample.config.yamlを参考にしてください。

# twitter user/pass to post
usernum : “3631571” # see your Feed of twitter
user : “username”
pass : “password”

## post with buzztter ratio
buzzratio : 0.3 # 30%

## search words for refav
#searchwords : [“ahokai”, “あほか”]

## block NG words
#blockngwords : “true”

## for debug
#nopost : “true”

0.0にすれば動作しなくなり、1.0にすると確実に空気を読みます。
なお、バズワードの取得元は自分のtimelineだけではなく、buzztterからもランダムに取得します。


■post前に発言を検閲し、NGワードが含まれていたら発言を再度作り直す
bot元にしたらbotが確実に犯罪予告しそうな人がいたので、安全な言葉を出すまで発言を再構築させて犯罪防止をする機能を追加。
ngwordsに正規表現を書いておく。

.*殺.*
.*死.*
.*糞.*
.*うんこ.*
.*爆破.*
.*爆発.*

安全な言葉を出すまで10回再提出させて、無理ならあきらめる仕様なのであまり多くすると何もしゃべれなくなる。

config.yamlで

## block NG words
#blockngwords : “true”


## block NG words
blockngwords : “true”

とコメントアウトを外せば検閲機能が有効になります。

検閲はpost3gram.rbの中で実装してます

0

ahokai rev.54以降でのDBファイル名変更、buzztter検索post

(ついに本気を出して絶賛修論執筆中だけど)ahokaiiの設計を少し修正した

これまでsqlite3のデータベースファイルを db_ngrams, db_postsという2つのファイルにしていたけど
db というファイル1つにまとめました。

理由は、特に2つに分ける意味は無かったからです。

commit 54以降のバージョンにアップデートするには、
db_postsの方にクロールした元twitterアカウントのデータが入っているので、それは消さずにdbにリネームして、n-gramのテーブルを追加すると良いですよ

mv db_posts db
rm db_ngrams
ruby migrate_ngrams.rb up
ruby make3gram.rb

忘れずにmake3gramし直す。


あと、ついでにBuzztterから検索してpostを構築する機能が付けてみた。
面白くなるかはわからないけど。


マルコフ連鎖でのpost構築は、今まで頭側から行っていたけど左右両方向へ伸ばすようにしたので
これで検索機能が付けられた

ruby post3gram.rb リナカフェ

「リナカフェ」を含むpostが作られる

make post with ‘リナカフェ’
リナ カフェ が 1
—search left 3-grams—
=” リナ カフェ 1
m =” リナ 1
‘ m =” 1
e ‘ m 1
– e ‘ 1
(h)ruby – e 1
—search right 3-grams—
カフェ が オススメ 1
が オススメ ! 1(t)
ruby-e’m=”リナカフェがオススメ!


Read more