クフでダローバルな日記

タフでもグローバルもない

Sinatraを使ってtwitter連携のwebアプリを作ってみた記録

ちょっと前に書いた記事を公開し忘れていたので公開します。

-----------------------------------
こんにちは。もうすぐクリスマスですね。

先月くらいにSinatraを勉強してみて、先週ようやくWebアプリらしいものを作れたので、これから勉強しようと思ってる人の参考になればと思いここまでの記録をしておこうと思います。

1.Sinatraを始めたきっかけ
もともとWebサービスには興味があって、Ruby on Railsを今までも何度か勉強していたんですが、「何度か」という言葉からわかるように始める度に挫折をしていました。当時はなぜ挫折していたのかも自分でわかっていなかったのですが、今考えると

  1. そもそもhtmlを使ってページを作ったことがあまり無い
  2. 自動化されすぎていて何をやっているのかわからない
  3. └→どうしてRailsが便利なのかわからない
  4. 作りたいもの・作れるもののイメージが湧かない

というのが原因だったのだと思います。html手打ち→phpRoRという時代の流れを見てきた方々にとってはRoRの便利さも分かりやすいのでしょうが、僕のような物心ついた頃にはSNSが流行していたゆとり世代にはいまいちぴんとこないものです。

そこで、まずRailsほど「便利」ではないけど「シンプル」なSinatraを使って、まずはなにか作ってみることを目標にしました。

2.勉強の道程
最初にしたことはやっぱりドットインストールのsinatra入門です。
Sinatra入門 (全17回) - プログラミングならドットインストール
ドットインストールのSinatra入門の素晴らしいところは、これが終われば掲示板を作れるところで、それさえ理解すればちょっと応用することでかなり多くのことに応用できることですね。この場合はSinatra,erb,ActiveRecord,jQueryの使い方を知ることが出来ました。
ちなみに今までドットインストールを試聴するときは純粋に「視聴」していたんですが、動画に合わせてソースコードを写経することでかなり理解も捗ったような気がします。

もともとTwitterbotを作っていた際にHeroku上でTwitterのツイートをDBに保存する術を何となく身に付けていたので、とりあえずDBとの連携の仕方がわかっただけで簡単なwebサービス(?)を作ることが出来ました。https://ynewsretrans-viewer.herokuapp.com/ です。
昔作ったyahoo newsの再翻訳botをまとめて見たり、タグ付け・ふぁぼしたりするサービスです。練習として作ったので大して凝ってませんが、とりあえず一つ作ってみることで何となくSinatraと言うものに対する距離感は縮まったんじゃないかと思います。
ちなみに、これを作るためにjQueryやBootstrapも少し勉強しました。と言っても、この二つは簡単なのでドットインストールとか日本語版のリファレンスを読めば基本的なことはすぐに使えるようになれました。

そして、最近作れたのがTwitter連投チャレンジです。友人や先輩には「邪魔だ」「不快だ」「害悪だ」などとだいぶ不評ですが、これくらいしかモチベーションを維持して作れるものがなかったのでお許し下さい(o_ _)o
OAuthを使ったログインとかの新しい知識は必要でしたが、基本的にRubyでプログラミングしているのと近い感覚なので、結局2,3日でおおまかな部分を完成させることが出来ました。
デザイン面とか超適当ですが、Sinatraとbootstrapとjqueryを使えば簡単なwebアプリならこんな気楽に作れるのかと感動です。

3.感想
今までは自分が楽しむもの・botくらいしか作れなかった自分が、webページを作れるようになっただけで世界がかなり広がったような気がします。Railsに挫折した僕のような人にはSinatraをオススメしたいところです。とはいえ、昨日の学科忘年会で「Railsはもう古い」みたいな噂を聞いて不安に震えています。
また、先ほど「こんな気楽に作れるのか」と言ったばかりですが、実際は悩みどころも多いです。というのも、色々な人に実際に使ってみたところ結構バグが多くて、テストの必要性をひしひしと感じています。やはり今後はrspecとかを使えるようにならなきゃいけないし、その後にRailsをやっと使えるようになるんだろうなって感じます。Railsへの道は長い……

勉強する上で特に参考になったページを羅列させていただきます。
Sinatra入門 (全17回) - プログラミングならドットインストール
簡単Sinatra!WebAPI・OAuth認証を使ってみよう - 角幸一郎 | type IT Academy

リプするとマルコフ連鎖で一句読む機能を@.haiku_searcherに追加しました

お待たせしました。新機能搭載です。

機能としては、@に「詠んで」を含むリプをすると、その人の過去200ツイートを取得し「一次マルコフ連鎖」を用いて俳句/川柳を作るというものです。ちょっとした人工知能(無能?)的なものだと思ってください。

また、「詠んで」に加えて「ちゃんと」も含むリプをすると「二次マルコフ連鎖」を用いるのでそれなりに文章として成立した俳句が出来るはずです。しかし、生成に時間がかかる、結局普通の俳句探索になりがち、あんまり面白くないという理由から、オススメしません。
こんな感じで、普通の俳句が見つけられやすいです。

もちろん、俳句のルールや季語認定の方法などは通常の偶然俳句ツイートbotのものを流用しています。詳しくはこちら↓
swimath2.hatenablog.com

マルコフ連鎖」と言ってもわからない人も多いかと思いますので、ちょっと解説してみようと思います。ちなみにマルコフ連鎖はしゅうまい君(@)や圧縮新聞(@)などでも使われているそうですね。
専門的に習ったわけでは全くなく、ただネット上の情報から知っただけの生半可な知識なので、間違いがあれば指摘していただけると幸いです。

マルコフ連鎖」とは

まず、「マルコフ連鎖」のwikipediaを見てみると

マルコフ連鎖とは、確率過程の一種であるマルコフ過程のうち、とりうる状態が離散的(有限または可算)なもの(離散状態マルコフ過程)をいう。
...
各時刻において起こる状態変化(遷移または推移)に関して、マルコフ連鎖は遷移確率が過去の状態によらず、現在の状態のみによる系列である。

とあります。要するに「過去どんな変化をしてきたかを気にせず、次どうなるかが今どうなっているかだけで決まる流れ」ということですかね。

まだまだわかりづらいと思うので、実際の日本語を例に解説してみます。
我輩は猫である。吾輩の名前は猫だ。猫だ。」
という文章を考えてみましょう。(文章として正しいか微妙ですが、マルコフ連鎖では文章の意味までは立ち入らないのであまり気にしないでください。)
この文章を形態素解析(品詞分解)してみると「我輩/は/猫/で/ある/。/吾輩/の/名前/は/猫/だ/。/猫/だ/。/」というふうに分解できます。

例えば「吾輩」という言葉の後に来るのは「は」か「の」。「で」のあとに来るのは「ある」だけ。というように調べていきまとめると、次のようになります。(矢印の先が後に来うる品詞)

f:id:SWIMATH2:20150320061854p:plain

この図に、各品詞の出現回数(「我輩」なら2、「猫」なら3)と、それぞれの品詞から次の品詞になる確率(「猫」が3回出たうち次の品詞が「で」となるのは1回、「だ」となるのは2回なので、それぞれの確率は1/3,2/3となります。(赤字))を書き込んだ図が下図となります。

f:id:SWIMATH2:20150320081304p:plain

これがマルコフ連鎖での「状態遷移図」というものであり、この図に従ってある状態から次にどうなるかを確率的に選ぶことが出来るわけです。

この説明じゃまだわからない人も多いかと思いますが、さらにグラフィカルにわかりやすくしたものがあったので紹介させていただきます。
Wokashi: 形態素解析からのマルコフ連鎖を可視化してみた


ちなみに、二次マルコフ連鎖とは一つ前の単語だけでなく、2つ前の単語まで含めた分類をします。
例えば一時マルコフ連鎖では「猫」のあとは「で」が1/3、「だ」が2/3でしたが、二次マルコフ連鎖では「は/猫」のあと「で」が1/2、「だ」が1/2、「。/猫」のあとは必ず「だ」のように、更に細かい分類をします。

細かい分類・分析をするため、一次マルコフ連鎖に比べより日常の言葉が生成されやすいのですが、分岐する方法が少ないということは生成される文章のパターンが少ないということなので、俳句となるものが見つかりづらいという欠点があります。

haiku_searcherの動き

botでは、この図に従って色々な動き方を試し、俳句となるものを見つけます。「スタート地点」を特に決めていないので、色々な品詞から調べ始めます。こんな感じで↓

f:id:SWIMATH2:20150320081346j:plain

ついでに言っておくと、ここでは俳句を探すのに「深さ優先探索」というものを行っています。今回はマルコフ連鎖がメインなので説明は省きますが、アルゴリズムとかに興味ある人は調べてみてください。
ちなみに僕はアルゴリズムとか全く得意じゃないので効率のいい手段が思いつきません。なんか良いのがあったら教えてください。(実装するとは言ってない)

おわりに

せっかく新機能をつけておいてアレなんですが、最近botのツイートが増えすぎてかなり頻繁に規制されているようなので、返信が来ない時は暫く時間を置いてからもう一回リプすると反応してくれるかもしれません。すみません。

っていうか、このbotrubyで書いてherokuで動かしているんですが、同じIPアドレスの二つのappに対してツイート規制が共有されるらしく、どうにか出来ないもんかって悩んでおります。(Twitter::Error::Forbidden: User is over daily status update limit. がめっちゃ出まくります。)何か解決策をご存じの方がいれば教えてくださいお願いします。

それから、緑の卵アイコンという何となく和風なものがたまたま出たのでそのまま使っていますが、せっかくだしアイコンも変えたいのでアイコン募集してます。自分で作るかもですが。フラットデザイン()。

今回の新機能追加にあたってはマルコフ連鎖について解説されている多くのページを参考にしましたが、ソースなどを特に参考にさせていただいたページを挙げておきます。
ググればもっと詳しい情報もでると思うので、興味を持った方はぜひ。
マルコフ連鎖でTwitter BOTを作る - FLYING
マルコフ連鎖で日本語をもっともらしく要約する - ザリガニが見ていた...。
マルコフ連鎖 - Wikipedia

偶然俳句ツイートbotの解説とルール説明してみます

久々のブログです。
先日、偶然俳句ツイートbotというものを作りました。

とは言っても、botでもツイートしたたように内容とアイディア自体はちょっと前に話題になった偶然短歌bot(@)やここで一句bot(@と一緒です。特にここで一句botについては、twitterリプする以外ほぼ同じなのでパクリと言われてもしたかないかもしれませんね。すみません。

今回はこちらのまとめていただいたtogetter↓がかなりbuzzったようで、かなりフォローしていただきました。
つぶやきから五七五を検出して報告してくる偶然俳句botとの戦い - Togetterまとめ
期待してフォローしていただいて嬉しいのですが、フォローしていただいただけでは俳句を探索しないので、botがフォロバするまで少々お待ちください。
また、フォローが増えすぎたため頻繁に規制されたり取得漏れが起きたりしているようなので、普通に俳句をツイートされても通知できないことが多いようです。ご了承ください。

どういう基準、仕組みで俳句を探索しているのか分からないとよく言われているようなので、ここでルールと仕組みを簡単に解説しておきます。

基本ルール

文章の解析はmecab+IPA辞書

形態素解析にはmecabIPA辞書を利用しています。と言っても何言ってるかわからない方も多いかと思いますが、端的に言うと文章を解析してくれるソフト的なものを使っているわけです。具体的には公式サイトを見ていただけると分かりやすいかと思います。
MeCab: Yet Another Part-of-Speech and Morphological Analyzer
例えば、「柿食えば鐘が鳴るなり法隆寺」というものをmecabを用いて解析すると

柿	名詞,一般,*,*,*,*,柿,カキ,カキ
食え	動詞,自立,*,*,五段・ワ行促音便,仮定形,食う,クエ,クエ
ば	助詞,接続助詞,*,*,*,*,ば,バ,バ
鐘	名詞,一般,*,*,*,*,鐘,カネ,カネ
が	助詞,格助詞,一般,*,*,*,が,ガ,ガ
鳴る	動詞,自立,*,*,五段・ラ行,基本形,鳴る,ナル,ナル
なり	助詞,接続助詞,*,*,*,*,なり,ナリ,ナリ
法隆寺	名詞,固有名詞,組織,*,*,*,法隆寺,ホウリュウジ,ホーリュージ

というように解析してくれるわけです。それぞれの分解した要素の最後にその言葉の読みがあるので、これを利用すれば575のリズムになっているものを見つけるプログラムが作れるわけです。
ちなみに僕はmecabを使ってみたのはこれが初めてで、練習のために作ってみたのがこのbotだったりします。

音のルール
  • 「ぁぃぅぇぉゃゅょ」は全部0音換算(「しゃ」などは1音)
  • 「ー」「っ」は一音
  • 読み方がわからない言葉(英単語、記号など)が含まれるものは判定しない
  • 字余りはNG

字余りについては、許容してしまうとかなりの文章が俳句認定されてしまうため、残念ながらNGとしました。
今は割と致命的なバグがあるので、そのうち修正します。(小声)
また、僕は俳句について知識が全然無いのでなんかおかしい所があれば教えてください…

上/中/下の句の最初の単語のルール

俳句の最初の単語の品詞としてOKなのは、
[名詞,動詞,形容詞,形容動詞, 副詞, 連体詞, 接続詞, 感動詞, 接頭詞, フィラー]
のどれかです。
さらに、最初の単語の細かいルールとして、

  • 非自立動詞や接尾語はNG
  • 「ぁ」など小さい文字から始まるのはNG

というものもあります。
例えば「みかん食え/鐘が鳴るな/法隆寺」みたいなのは中の句が助詞から始まってるのでダメってことです。

上/中/下の句の最後の単語のルール
  • 接頭詞はNG

今のところこれだけです。
例えば「ちょっとまて/ちょっとまってよ/おにいさん」はOKですが「ちょっとまて/ちょっとまって/にいさーん」は接頭詞「お」が中の句の末尾に来ているのでNGということです。

下の句の最後の単語のルール
  • 活用語の場合、終止形のみ

要するに、連用止などを禁止するわけです。

全体的に割と厳しいルールを適用しているのですが、これはルールを緩くするとどう見ても575じゃないものまで575と認定してしまいがちで、さらにツイート数が増えると規制につながりやすくなるためです。最初はもっとザルだったんですが、リプによる指摘に対応していたら大分精度が上昇しました。ビッグデータって凄い(?)。

季語判定

どうにかしてここで一句botと差別化しようと思った苦肉の策がこちらの季語判定になります。
お気づきの方も多いと思いますが、季語は読みの音によって判定しています。これは掛詞に対応するためです。もちろん嘘です。
じゃあなぜ音で判定しているかというと、普通に単語で判定しようと思うと滅多に季語がなくなってしまい、つまらないからです。異論は認めません。
季語については現代俳句データベースなどからお借りしました。現在2529個の季語が登録されています。
ちなみにボジョレー・ヌーボー(冬)とかもあるようなので、これを含む俳句ができるのを楽しみにしてます。

即リプの仕組み

どうやら秒速リプが受けているようなのでちょっと解説しておきますが、実はこれ自体はそれほど難しいことをしていません。
というのも、TwitterにはStreaming APIというものがあり、例えばechofonなどのアプリでは、流れてきた情報(ツイート)からアイコン画像とユーザー名、ツイート内容だけ取り出して一つの「ツイート」として表示しているわけです。だから一々ロードする必要もないし、ツイートされてすぐ表示されているわけですね。

botではこのStreaming APIを利用し、流れてきたツイートからツイート内容を取り出し、俳句認定と季語探索をしてツイートしてます。
ちなみに現状ではツイート内容から俳句を探し、季語認定をするのに約0.5秒、ツイートするのに約0.3秒の計0.8秒もかかってしまっているので、暇があれば少し高速化しようかと思っています。

最後に

少し解説させていただきましたが、僕よりもここで一句botや偶然短歌botの作者さんの方が機能や精度が良いので、そちらも見ていただけると嬉しいです。
Ruby - Slackの会話を元に一句詠む - Qiita
形態素解析エンジンMeCabにて文章中から短歌を抽出 - inaniwa3's blog

新しい機能を追加しようと鋭意努力しているのですが、今月は若干忙しいので気ままにお待ち戴けると幸いです。

以下、参考文献です。
現代俳句データベース
MeCab: Yet Another Part-of-Speech and Morphological Analyzer
『東京都版国語便覧』浜島書店

3ステップで自分の同時通訳twitter botを作りましょう

お久しぶりです。ようやく学科にも慣れてきましたが、色々とつらいです。

さて、最近もちょくちょくtwitter botを作っていたわけですが、ちょっと前にこちらの記事が人気を博しているのを読みました。
自分をコピーするbotを作る - naoty.to_s
Deploy To Herokuボタンってそうやって使えるのか……と感化され、楽しそうだったので僕も作ってみました。
mazamachi/twitrans_bot

概要

グローバル化している今、あなたのツイートも世界に向けて発信しましょう。え?語学力が足りない?だったら翻訳してもらえばいいんです。Microsoftの高性能翻訳があなたのツイートを自動で翻訳し、botとしてツイートしてくれます。
基本となる物は既に作ってあるのでプログラミングスキルは一切不要です。
必要なステップはたった3つ。
1. Microsoftアカウントを翻訳用に認証
2. Twitter bot用アカウントの作成と認証
3. 既存のコードをHeroku上にアップして設定
です。
※今回は残念ながら鍵垢(非公開アカウント)には対応していません。時間があったら作ってみます。

Microsoftアカウントを翻訳用に認証

まずは翻訳してくれるようにmicrosoftで登録する必要があります。Microsoft Translator | Microsoft Azure Marketplace にアクセスし、右にあるリストから0円のものを購入しましょう。無料プランだけでも月2,000,000文字が翻訳できるので、ツイートを翻訳する程度なら全く問題ないはずです。
Microsoftアカウントを持っていなければ作るようお願いします。
f:id:SWIMATH2:20141121174610p:plain

次はSign In にアクセスし、アプリ登録をクリック。クライアントIDや名前、説明は自分で好きなもので構いません。リダイレクトURIも適当で構いません。この時表示されるクライアントIDと顧客の秘密をメモしておいてください。
大事なものなので人には教えないようにしてください
f:id:SWIMATH2:20141121174703p:plain

Twitter bot用アカウントの作成と認証

Welcome to Twitter - Login or Sign upにアクセスし、bot用アカウントを作ってください。これに関しては説明は不要でしょう。

次にTwitter Application Managementにアクセスし、Create New Appを押してMicrosoftの時と同様アプリ登録をします。ただし、この時ログインするアカウントはbotのアカウントにしてください。名前や紹介やURLを適当に入力して同意して進むと、botが作成されます。
f:id:SWIMATH2:20141121174834p:plain
ただし、この段階ではこのbotは投稿ができないので一番右の"Permissions"からRead and Writeに変更してUpdate Settingsを押してください。
f:id:SWIMATH2:20141121174904p:plain
その後「Keys and Access Tokens」タブの下の方から Create my access tokenを押してください。以下のように表示されたConsumer Key,Consumer Secret,Access Token,Access Token Secretをメモしておいてください。
f:id:SWIMATH2:20141121174920p:plain

既存のコードをHeroku上にアップして設定

最後です。mazamachi/twitrans_bot · GitHubにアクセスし、deploy to herokuボタンを押してください。(herokuのアカウントを持っていなければ作る必要があります)
下の方にパラメータの入力欄があるので、これまでにメモしておいたキーなどを入力してください。

パラメータ名 入力するもの
LANGUAGE_FROM 自分がツイートする言語 ※1
LANGUAGE_TO 翻訳した言語 ※1
MENTION_NOT_INCLUDE リプライを翻訳するか ※2
USER_IDS 翻訳させるアカウントのid(","で区切ってください) ※3
TRANS_CLIENT_ID MicrosoftでメモしたクライアントID
TRANS_CLIENT_SECRET Microsoftでメモした顧客の秘密
BOT_CONSUMER_KEY TwitterのConsumer Key
BOT_CONSUMER_SECRET TwitterのConsumer Secret
BOT_ACCESS_TOKEN TwitterAccess Token
BOT_ACCESS_TOKEN_SECRET TwitterAccess Token Secret

※1 言語の種類はen,jaのように略称で入力してください。それぞれ1つだけです。言語一覧はTranslator Language Codesで参照できます。
※2 リプライを翻訳するか決めます。デフォルトでは含めないようになっているので、リプライを含めたければこれを false に変えてください。(FALSEやFalseでもダメです)
ただしあまりオススメはしません。というのも、翻訳されたツイートがリプライとなって相手に届いてしまうからです。若干迷惑ですね。
※3 例えば、today_prime_bot,today_pi_bot, HatenastarRank のようにしてください。

そうしたらページ最下部の Deploy for Free をクリックして、最後の設定をします。まだbotは登録されただけで動いていないので Resources からDynosのEditをクリック、ドラッグして1に変えてください。(止めたいときは逆に0にすれば良いです)
f:id:SWIMATH2:20141121174943p:plain


以上でbot完成です。お疲れ様でした。もし何か修正したければ HerokuのSettingでReveal Config Varsから修正することが出来ます。
実際に動かした方でなにか不具合があれば、ぜひコメントなどでご報告をお願いします。アドバイスとかもしていただければ泣いて喜びます。