モテる! Node.js でつくる twitter ボット制作

9,008 views

Published on

Node.js の環境構築から、一本進んだ Twitter のボット制作までを紹介します。

Published in: Technology
0 Comments
22 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,008
On SlideShare
0
From Embeds
0
Number of Embeds
718
Actions
Shares
0
Downloads
38
Comments
0
Likes
22
Embeds 0
No embeds

No notes for slide

モテる! Node.js でつくる twitter ボット制作

  1. 1. モテる! Node.js でつくる Twitter ボット制作 X Presented by @hecomi
  2. 2. introductionはじめに
  3. 3.                  / ̄ ̄ ̄ ̄ ̄ ̄\ 
           /             \ 
                  _______ 
           /     /           \| 
           .′ j/  ,. -―――‐- .,   〉 
        /   j|:..//-∠、. . . . . /--. \{ 
         〈_/上|. / o  \/∨ o V/庁=、 
          \ |/ ┌──── ┐ ∨ソ/ 
    ___________
            )、_;,. !         | ;_/    
  /                 \
              ⌒ 介:. 、 ____,,ノイ{     <  のぉどじぇーえすって     | 
               ⌒7⌒\/\/\⌒ 
  |  なにするです?        |
               / .:::::::::::::::::::::::::::::::::::::::::::::.\                  ,′ V/, ○∨  ∧ 
  \___________/             /.::::::::::::::   ´ ̄ ̄ ̄ ̄` 、:::::.\               j__,V/○ j  ′〉 
              {___,ノ  人__ク 
            / .::::::::::::/   ____  \:::::::|                _,ノ\冖┘ へ. └冖 \_ 
         ___/ .:::::::::::::∨   / \. . . . /^\ \,′            {丈____\/-―-\/___丈}           \:::::::::::::::::::::::|  // ⌒ |/∨ ⌒ |\__〉           `  ――r┴‐| /  o      o│./┴┐  ___________
                     \⌒′ r――――┐ レ  /  /                 \
                         __                    >ヘ  |      │ ,< <  よくわからないので      |                 ,... -―――‐/ \ー- 、  __                    ^⌒T>乂__   ...ノ イ⌒^  |  おことわりするです      |
               ./: : : : : : : : : :/    \__/ .‘,             /: : ,---- ̄ ̄  ____    .‘,                     ∠ニ=干‐ 厂}‐r‐厂}  \___________/            /: : : : |    ., - ´   ,. -,l .\ ‘,__                        { . . . │ |=イ.│|=イ           /: : : : : : :.|   / ⌒     l____丿.⌒ヽ  /                 _,,..ノ\ . .│ | 八 |│/          /: : : : : : :/  ./               | ./                  /. . . . . . \_|_j,′.〉 ̄         /: : : : : :/   ./l    o     .__   o ∨                \ . . . . . . . . . . . (__)ヘ        ./: : : : : :‘,   ./.ヽ   ____|___|___ .|       .,: : : : : : : :‘, _ -ー´   |           | .|    ___________
         {\. . . . . . . . . . ∧. . 〉                             、::\___/::::}/       l: : : : : : : : /       .|           | |  /                 \
                  \::::::::::::::::::::,′:/       |: : : : : : : :\       ヽ          / ./ <  さーばさいどでじゃば     |       |: : : ._------|ー‐―-、 _  .\______//                   \::::::::::::/.::::,′       |: :/       ̄ ̄ヽ _>ー――――‐ ´  |  すくりぷとじっこうしたり?  |
                    {三三}ニニ}       |/            ̄/: :|__\ <> |ヽ  \___________/                   /: : : : : : └-\/.人                     {___┐┐                  .|: : : :/: : : : : : : : : : : :‘,                   \:/: : : : : : : : : :○: : :‘,                    /: : : : : : : : : : : : : : : :‘,                   〈: : : : : : : : : : : : : : : : : : |                    `ー-...._: : : : : : : /l: :_/                    .‘,: : :`ー---/ : ̄/                     ‘,: : : : : :./: : : /                      .‘,: : : : / : /                       l ̄ ̄〉 ̄〉                        ̄ ̄ ̄ ̄
  4. 4. 本発表について•  となってる人が多いと思うので…•  実際に Node.js 環境を構築して、その上 で Twitter ボットを動かしてみます。 –  おうむ返しボット、特定のキーワードに反応 するボット、人工無能ボットから、一歩進ん で形態素解析ボットを紹介します。
  5. 5. introductionのぉどじぇーえす?

  6. 6. Node.js?•  http://nodejs.jp/•  サーバサイドで JavaScript を実行 –  エンジンは v8
  7. 7. 何が出来るの?•  ブラウザの JavaScript で出来なそうな ことがサーバ上で出来ます
  8. 8. 何が出来るの?•  ブラウザの JavaScript で出来なそうな ことがサーバ上で出来ます –  ファイル操作とか var fs = require(fs); fs.writeFile(log.txt, ‘Hello, world!, function(err) {    if (err) throw err;    console.log(Success!); });
  9. 9. 何が出来るの?•  ブラウザの JavaScript で出来なそうな ことがサーバ上で出来ます –  http サーバ立てたりとか var http = require(http); http.createServer(function(req, res) {     res.writeHead( 200, {Content-Type: text/plain} );     res.write(Hello, world!n);     res.end(); }).listen(3000);
  10. 10. 何が出来るの?•  ブラウザの JavaScript で出来なそうな ことがサーバ上で出来ます –  http サーバ立てたりとか var http = require(http); http.createServer(function(req, res) {     res.writeHead( 200, {Content-Type: text/plain} );     res.write(Hello, world!);     res.end(); }).listen(3000);
  11. 11. installいんすとーる
  12. 12. インストールしよう•  Windows 環境下(http://nodejs.org/) クリックしてインストールするだけ
  13. 13. インストールしよう•  Mac / Linux 環境下 –  バージョン管理も含めて nave がオススメ •  https://github.com/isaacs/nave
  14. 14. インストールしよう•  node.js と npm のインストール $ mkdir ~/.nave $ cd ~/.nave $ git clone git://github.com/isaacs/nave.git $ ~/.nave/nave/nave.sh use latest $ $ curl https://npmjs.org/install.sh | sh•  ちなみに結構コンパイル時間かかります•  参考 –  naveを使ったnode.jsインストールと、最近のnpmの使い方 - ラシウラ –  http://d.hatena.ne.jp/bellbind/20110530/1306764093
  15. 15. インストールしよう•  インストールされたか確認 –  Windows の人はコマンドプロンプト上で $ node –v v0.8.9 $ npm –v V1.1.61•  これで OK!
  16. 16. Hello, world!はろーわーるど
  17. 17. 対話コンソール$ node> console.log(Hello, world!); // これを打つHello, world!undefined> (Ctrl+D 押下)$
  18. 18. ファイル$ cat helloworld.jsconsole.log(Hello, world!);$ node helloworld.jsHello, world!
  19. 19. おまけ:ブラウザ// helloworld.jsvar http = require(http);http.createServer(function(req, res) {     res.writeHead(200, {Content-Type: text/plain});     res.write(Hello, world!n);     res.end();}).listen(3000);$ node helloworld
  20. 20. Make twitter bot!ついったーぼっとせいさく
  21. 21. Consumer Key / Access Token1.  適当な Twitter アカウントを作成2.  Twitter の開発者サイトより 1.  Consumer Key / Consumer Secret 2.  Access Token / Access Token Secret を取得する※ 開発者サイト: https://dev.twitter.com/•  ※参考: –  twitterアクセストークンなどの取得方法(WordPress更新通知用) –  http://musilog.net/webdesign/my-works/twitter-oauth-wp-to-twitter.php
  22. 22. Twitter モジュール導入•  npm でインストール $ mkdir twitter_bot $ cd twitter_bot $ npm install twitter npm http GET https://registry.npmjs.org/twitter npm http 200 https://registry.npmjs.org/twitter npm http GET https://registry.npmjs.org/twitter/-/ twitter-0.1.18.tgz npm http 200 https://registry.npmjs.org/twitter/-/ twitter-0.1.18.tgz …(ry•  依存関係も含めて必要なモジュールをイ ンストールしてくれます
  23. 23. npm•  npm は node package manager の略•  package 数は 15006 個!(2012/09/22 現在)•  使い方 –  npm install hoge •  実行したディレクトリ下に node_modules ディレ クトリを作成してそこにモジュールを展開 •  実行したディレクトリ下のみで使用できる –  npm install -g hoge •  どのディレクトリからでも使える
  24. 24. Twitter で はろーわーるど•  早速使ってみましょう! var twitter = require(twitter); モジュールのロード var bot = new twitter({ consumer_key : xxxxxxxxxx, consumer_secret : xxxxxxxxxx, さきほど取得した access_token_key : xxxxxxxxxx, 各キーを入力 access_token_secret : xxxxxxxxxx }); Twitter に Hello, world! とつぶやく。 bot.updateStatus(Hello, world!, function (data) { つぶやいたら呼ばれる console.log(data); コールバック関数。 }); data には Twitter から 返ってきた JSON が 入っている。
  25. 25. 結果$ node twitter{ entities: { hashtags: [], user_mentions: [], urls: [] }, retweet_count: 0, id_str: 249420311064358913, place: null, in_reply_to_user_id: null, favorited: false, in_reply_to_status_id_str: null, coordinates: null, created_at: Sat Sep 22 08:10:10 +0000 2012, in_reply_to_user_id_str: null, contributors: null, user:…(ry
  26. 26. Streaming API を利用•  twitter モジュールの説明: –  https://github.com/jdub/node-twitter•  stream 接続 bot.stream(user, function(stream) { stream.on(data, function(data) { console.log(data); // ズラーッと TL の情報が表示される }); });※ ローカル環境の Linux 機で試してみると $ node bot とコマンドを実行してもすぐ終了してしまう場合があります。原因は分かる方いらっしゃいましたら @hecomi まで教えて下さい m(_ _)m
  27. 27. 色んなボットを作ってみよう!•  例として3つ紹介します –  おうむ返しボット –  特定のキーワードに反応するヤツ –  人工無脳
  28. 28. おうむ返しボットvar BOT_ID = hecomiroid; この ID をミスるとループしまくるので注意!bot.stream(user, function(stream) { stream.on(data, function(data) { if ( !(text in data) ) { Streamin API 接続直後は console.error([ERROR] invalid data); following ID 一覧が降ってき return; たりするので、そういったゴミ } を除外。 var twUserId = data.user.screen_name , replyStr = data.text.replace(new RegExp(^@ + BOT_ID + ), ) , isMention = (data.in_reply_to_user_id !== null) ; @の部分を除去 if (!isMention || twUserId === BOT_ID) return; bot.updateStatus(@ + id + + text, function (data) { console.log(data); }); 他人から自分へのつぶやき以外は除外 });});
  29. 29. 特定のキーワードに反応するヤツvar BOT_ID = hecomiroid;bot.stream(user, { track: Vim }, function(stream) { stream.on(data, function(data) { 自分の TL に加えて、検索ワー if ( !(text in data) ) { ドを追加できる console.error([ERROR] invalid data); return; } if (data.user.screen_name === BOT_ID) return; var twStr = data.user.name + さんが、" + data.text + "って呟いた; bot.updateStatus(twStr, function (data) { console.log(data); }); });});
  30. 30. 人工無脳var printf = require(printf); // npm install printfvar BOT_ID = hecomiroid;var replyMap = { こんにち(は|わ) : ちょりーっす!, おやすみ(なさい)? : いい夢見ろよ, うー : (」・ω・)」うー!(/・ω・)/にゃー!, (.*?)なう : %sするのが許されるのは小学生までだよねー!};bot.stream(user, function(stream) { stream.on(data, function(data) { キーワードと返信する文章を if ( !(text in data) ) { 正規表現で書いて console.error([ERROR] invalid data); return; 引っ掛かったら返事をつぶやく } if (data.user.screen_name === BOT_ID) return; for (var regex in replyMap) { if ( new RegExp(regex).test(data.text) ) { var replyStr = printf(replyMap[regex], RegExp.$1); var tweetStr = printf(@%s %s, data.user.screen_name, replyStr); bot.updateStatus(tweetStr, function (data) { console.log(data); }); return; } }});
  31. 31. できた!•  というわけで Twitter ボットが出来まし た。•  最後に、もう一歩進んだボット制作を紹 介して終わりにします。
  32. 32. Make more interesting bot!もういっぽふみこんでみる
  33. 33. もっと色々やりたい•  色んな(JavaScriptには無い)プログラ ムやライブラリと連携してもっと面白い ことをつぶやかせたい、と思いません か?
  34. 34. もっと色々やりたい•  色んな(JavaScriptには無い)プログラ ムやライブラリと連携してもっと面白い ことをつぶやかせたい、と思いません か?•  それ、簡単にできます!
  35. 35. もっと色々やりたい•  色んな(JavaScriptには無い)プログラ ムやライブラリと連携してもっと面白い ことをつぶやかせたい、と思いません か?•  それ、簡単にできます!•  例として MeCab を使った形態素解析ボッ トを作ってみようと思います。•  簡単な方法と大変な方法の2つを紹介し ます。
  36. 36. MeCab のインストール•  MeCab: Yet Another Part-of-Speech and Morphological Analyzer –  http://mecab.googlecode.com/svn/trunk/mecab/ doc/index.html#download•  Windows ならインストーラ –  インストール後は環境変数へ登録•  mac なら –  brew install mecab mecab-ipadic•  Linux なら –  sudo aptitude install mecab mecab-ipadic-utf8
  37. 37. ① 簡単な方法•  コンソール上で実行して結果をパースvar exec = require(child_process).exec;exec(ls, function(err, stdout, stderr) { console.log(stdout);});•  こんな風にコマンドの実行結果を文字列 で受け取ることができますので、後はパ ースすれば OK です。
  38. 38. MeCab の結果をパースvar exec = require(child_process).exec , fs = require(fs) , TMP_TXT_FILE_NAME = __tmp__.txt;function parse(str, callback) { (ちなみに fs.writeFile(TMP_TXT_FILE_NAME, str, function(err) {   echo ‘hogehoge’ | mecab if (err) callback(err, null); を利用しても OK です。ファイルに exec(mecab + TMP_TXT_FILE_NAME, function(err, stdout, stderr) {  一時書きだしたのは windows 環境  での文字化けを避けているからです) if (err) callback(err, null); var mecabResultArr = [] , mecabResultStr = stdout.split(n) ; 解析する文章を for (var i in mecabResultStr) { 一時ファイルに書き出す var wordInfoArr = []; if (mecabResultStr[i].indexOf(EOS) === 0) break; /([^s]+)s+([^s]+)/.test(mecabResultStr[i]); wordInfoArr.push(RegExp.$1); MeCab を実行して wordInfoArr = wordInfoArr.concat(RegExp.$2.split(,)); mecabResultArr.push(wordInfoArr); 結果をパースする } exec(rm + TMP_TXT_FILE_NAME, function(err, stdout, stderr) { if (err) callback(err, null); callback(null, mecabResultArr); }); 一時ファイルを削除 }); });}parse(すもももももももものうち, function(err, result) { console.log(result); });
  39. 39. 結果$ node mecab[ [ すもも, 名詞, 一般, *, *, *, *, すもも, スモモ, スモモ ], [ も, 助詞, 係助詞, *, *, *, *, も, モ, モ ], [ もも, 名詞, 一般, *, *, *, *, もも, モモ, モモ ], [ も, 助詞, 係助詞, *, *, *, *, も, モ, モ ], [ もも, 名詞, 一般, *, *, *, *, もも, モモ, モモ ], [ の, 助詞, 連体化, *, *, *, *, の, ノ, ノ ], [ うち, 名詞, 非自立, 副詞可能, *, *, *, うち, ウチ, ウチ] ]
  40. 40. 別の JS から使えるようにするvar exec = require(child_process).exec , fs = require(fs) , TMP_TXT_FILE_NAME = __tmp__.txt; module.exports すると別のファイルからこの 関数を使えるようになるmodule.exports = function(str, callback) { fs.writeFile(TMP_TXT_FILE_NAME, str, function(err) { if (err) callback(err, null); exec(mecab + TMP_TXT_FILE_NAME, function(err, stdout, stderr) { if (err) callback(err, null); var mecabResultArr = [] , mecabResultStr = stdout.split(n) ; for (var i in mecabResultStr) { var wordInfoArr = []; if (mecabResultStr[i].indexOf(EOS) === 0) break; /([^s]+)s+([^s]+)/.test(mecabResultStr[i]); wordInfoArr.push(RegExp.$1); wordInfoArr = wordInfoArr.concat(RegExp.$2.split(,)); mecabResultArr.push(wordInfoArr); } exec(rm + TMP_TXT_FILE_NAME, function(err, stdout, stderr) { if (err) callback(err, null); callback(null, mecabResultArr); }); }); });}
  41. 41. 別の JS から使うvar parse = require(./parse.js);parse(すもももももももものうち, function(err, result) { console.log(result);});
  42. 42. 形態素分析ボット
 (おうむ返しボットを改造)•  つぶやく部分を以下のように変更すると 形態素解析ボットが出来ますparse(mentionStr, function(err, mecabResult) { var replyStr = ; mecabResult.forEach(function(wordInfoArr) { replyStr += printf(%s[%s] , wordInfoArr[0], wordInfoArr[1]); }); var tweetStr = printf(@%s %s, data.user.screen_name, replyStr); bot.updateStatus(tweetStr, function (data) { console.log(data); });});
  43. 43. ② 大変な方法•  C/C++ でモジュールを書く –  面倒ですが作れば速いです•  v8 のお作法に従って書けばOK•  詳しく解説しようとすると時間足りない ので、詳細は以下をご参照下さい m(_ _)m•  node.js の mecab addon 作った - 凹みTips※ –  http://d.hatena.ne.jp/hecomi/20120611/1339347112※ ここでは node-waf をコンパイルツールとして使っていますが、最近は node-gyp に置き換わったみたいです。
  44. 44. Summaryおわりに
  45. 45. まとめ•  Node.js の環境を整えました•  Twitter に呟くボットを作ってみました•  一歩踏み込んだ処理をするボットを作っ てみました
  46. 46. Appendixおまけ
  47. 47. おまけ - ネストを浅く•  非同期処理を繰り返すとネストがどんど ん深くなっていきますvar exec = require(child_process).exec;exec(echo hoge, function(err, stdout, stderr) { console.log(stdout); exec(echo fuga, function(err, stdout, stderr) { console.log(stdout); exec(echo piyo, function(err, stdout, stderr) { console.log(stdout); }); });});•  これを解決する方法は色々ありますが、 async.js あたりがおすすめです。
  48. 48. おまけ - ネストを浅くvar exec = require(child_process).exec , async = require(async);async.series([ function(next) { exec(echo hoge, function(err, stdout, stderr) { console.log(stdout); next(null); }); }, function(next) { exec(echo fuga, function(err, stdout, stderr) { console.log(stdout); next(null); }); }, function(next) { exec(echo piyo, function(err, stdout, stderr) { console.log(stdout); next(null); }); }]);
  49. 49. おまけ - ネストを浅く•  async.js には他にもパラで処理したり、 引数を次々と渡して行ったりと色んなパ ターンで書けます。•  参考: –  async.jsでフロー制御 - すぎゃーんメモ –  http://d.hatena.ne.jp/sugyan/ 20110605/1307240191
  50. 50. おまけ - ネストを浅く•  非同期処理を繰り返すとネストがどんど ん深くなっていきますvar exec = require(child_process).exec;exec(echo hoge, function(err, stdout, stderr) { console.log(stdout); exec(echo fuga, function(err, stdout, stderr) { console.log(stdout); exec(echo piyo, function(err, stdout, stderr) { console.log(stdout); }); });});•  これを解決する方法は色々ありますが、 async.js あたりがおすすめです。
  51. 51. おまけ - 例外処理•  例外が処理されないと Node.js は…
  52. 52. おまけ - 例外処理•  例外が処理されないと Node.js は… _人人人人人人_
 > 突然の死 <
  ̄^Y^Y^Y^Y^Y^ ̄ します。
  53. 53. おまけ - 例外処理•  なので以下のようなコードで例外を補足 して処理してあげます。process.on(uncaughtException, function (err) { console.log(uncaughtException => + err);});•  参考 –  node.jsの最低限の例外処理 - motsatのブログ –  http://d.hatena.ne.jp/bellbind/20110530/1306764093
  54. 54. おわりend

×