Your SlideShare is downloading. ×

Title

96
views

Published on

Desc

Desc


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
96
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. モテる! Node.js でつくる Twitter ボット制作 X Presented by @hecomi
  • 2. introduction はじめに
  • 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. 本発表について •  となってる人が多いと思うので… •  実際に Node.js 環境を構築して、その上 で Twitter ボットを動かしてみます。 –  おうむ返しボット、特定のキーワードに反応 するボット、人工無能ボットから、一歩進ん で形態素解析ボットを紹介します。
  • 5. introduction のぉどじぇーえす?

  • 6. Node.js? •  http://nodejs.jp/ •  サーバサイドで JavaScript を実行 –  エンジンは v8
  • 7. 何が出来るの? •  ブラウザの JavaScript で出来なそうな ことがサーバ上で出来ます
  • 8. 何が出来るの? •  ブラウザの JavaScript で出来なそうな ことがサーバ上で出来ます –  ファイル操作とか var fs = require('fs'); fs.writeFile('log.txt', ‘Hello, world!', function(err) {    if (err) throw err;    console.log('Success!'); });
  • 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. 何が出来るの? •  ブラウザの 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. install いんすとーる
  • 12. インストールしよう •  Windows 環境下(http://nodejs.org/) クリックしてインストールするだけ
  • 13. インストールしよう •  Mac / Linux 環境下 –  バージョン管理も含めて nave がオススメ •  https://github.com/isaacs/nave
  • 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. インストールしよう •  インストールされたか確認 –  Windows の人はコマンドプロンプト上で $ node –v v0.8.9 $ npm –v V1.1.61 •  これで OK!
  • 16. Hello, world! はろーわーるど
  • 17. 対話コンソール $ node > console.log('Hello, world!'); // これを打つ Hello, world! undefined > (Ctrl+D 押下) $
  • 18. ファイル $ cat helloworld.js console.log('Hello, world!'); $ node helloworld.js Hello, world!
  • 19. おまけ:ブラウザ // helloworld.js 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); $ node helloworld
  • 20. Make twitter bot! ついったーぼっとせいさく
  • 21. Consumer Key / Access Token 1.  適当な 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. 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. npm •  npm は node package manager の略 •  package 数は 15006 個!(2012/09/22 •  使い方 現在) –  npm install hoge •  実行したディレクトリ下に node_modules ディレ クトリを作成してそこにモジュールを展開 •  実行したディレクトリ下のみで使用できる –  npm install -g hoge •  どのディレクトリからでも使える
  • 24. Twitter で はろーわーるど •  早速使ってみましょう! var twitter = require('twitter'); var bot = new twitter({ consumer_key consumer_secret access_token_key access_token_secret }); : : : : 'xxxxxxxxxx', 'xxxxxxxxxx', 'xxxxxxxxxx', 'xxxxxxxxxx' モジュールのロード さきほど取得した 各キーを入力 Twitter に Hello, world! とつぶやく。 bot.updateStatus('Hello, world!', function (data) { console.log(data); }); つぶやいたら呼ばれる コールバック関数。 data には Twitter から 返ってきた JSON が 入っている。
  • 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. 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. 色んなボットを作ってみよう! •  例として3つ紹介します –  おうむ返しボット –  特定のキーワードに反応するヤツ –  人工無脳
  • 28. おうむ返しボット この ID をミスるとループしまくるので注意! var BOT_ID = 'hecomiroid'; 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. 特定のキーワードに反応するヤツ 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. 人工無脳 var printf = require('printf'); var BOT_ID = 'hecomiroid'; var replyMap = { 'こんにち(は|わ)' 'おやすみ(なさい)?' 'うー' '(.*?)なう' }; // npm install printf : : : : 'ちょりーっす!', 'いい夢見ろよ', '(」・ω・)」うー!(/・ω・)/にゃー!', '%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. できた! •  というわけで Twitter ボットが出来まし た。 •  最後に、もう一歩進んだボット制作を紹 介して終わりにします。
  • 32. Make more interesting bot! もういっぽふみこんでみる
  • 33. もっと色々やりたい •  色んな(JavaScriptには無い)プログラ ムやライブラリと連携してもっと面白い ことをつぶやかせたい、と思いません か?
  • 34. もっと色々やりたい •  色んな(JavaScriptには無い)プログラ ムやライブラリと連携してもっと面白い ことをつぶやかせたい、と思いません か? •  それ、簡単にできます!
  • 35. もっと色々やりたい •  色んな(JavaScriptには無い)プログラ ムやライブラリと連携してもっと面白い ことをつぶやかせたい、と思いません か? •  それ、簡単にできます! •  例として MeCab を使った形態素解析ボッ トを作ってみようと思います。 •  簡単な方法と大変な方法の2つを紹介し ます。
  • 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. ① 簡単な方法 •  コンソール上で実行して結果をパース var exec = require('child_process').exec; exec('ls', function(err, stdout, stderr) { console.log(stdout); }); •  こんな風にコマンドの実行結果を文字列 で受け取ることができますので、後はパ ースすれば OK です。
  • 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) { 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); }); }); }); } (ちなみに   echo ‘hogehoge’ | mecab を利用しても OK です。ファイルに  一時書きだしたのは windows 環境  での文字化けを避けているからです) 解析する文章を 一時ファイルに書き出す MeCab を実行して 結果をパースする 一時ファイルを削除 parse('すもももももももものうち', function(err, result) { console.log(result); });
  • 39. 結果 $ node mecab [ [ 'すもも', '名詞', '一般', '*', '*', '*', '*', 'すもも', 'スモモ', 'スモモ' ], [ 'も', '助詞', '係助詞', '*', '*', '*', '*', 'も', 'モ', 'モ' ], [ 'もも', '名詞', '一般', '*', '*', '*', '*', 'もも', 'モモ', 'モモ' ], [ 'も', '助詞', '係助詞', '*', '*', '*', '*', 'も', 'モ', 'モ' ], [ 'もも', '名詞', '一般', '*', '*', '*', '*', 'もも', 'モモ', 'モモ' ], [ 'の', '助詞', '連体化', '*', '*', '*', '*', 'の', 'ノ', 'ノ' ], [ 'うち', '名詞', '非自立', '副詞可能', '*', '*', '*', 'うち', 'ウチ', 'ウチ' ] ]
  • 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. 別の JS から使う var parse = require('./parse.js'); parse('すもももももももものうち', function(err, result) { console.log(result); });
  • 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. ② 大変な方法 •  C/C++ でモジュールを書く –  面倒ですが作れば速いです •  v8 のお作法に従って書けばOK •  詳しく解説しようとすると時間足りない ので、詳細は以下をご参照下さい m(_ _)m •  node.js の mecab addon 作った - 凹みTips※ –  http://d.hatena.ne.jp/hecomi/20120611/1339347112 ※ ここでは node-waf をコンパイルツールとして使っていますが、最近は node-gyp に置き換わったみたいです。
  • 44. Summary おわりに
  • 45. まとめ •  Node.js の環境を整えました •  Twitter に呟くボットを作ってみました •  一歩踏み込んだ処理をするボットを作っ てみました
  • 46. Appendix おまけ
  • 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. おまけ - ネストを浅く 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. おまけ - ネストを浅く •  async.js には他にもパラで処理したり、 引数を次々と渡して行ったりと色んなパ ターンで書けます。 •  参考: –  async.jsでフロー制御 - すぎゃーんメモ –  http://d.hatena.ne.jp/sugyan/ 20110605/1307240191
  • 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. おまけ - 例外処理 •  例外が処理されないと Node.js は…
  • 52. おまけ - 例外処理 •  例外が処理されないと Node.js は… _人人人人人人_
 > 突然の死 <
  ̄^Y^Y^Y^Y^Y^ ̄ します。
  • 53. おまけ - 例外処理 •  なので以下のようなコードで例外を補足 して処理してあげます。 process.on('uncaughtException', function (err) { console.log('uncaughtException => ' + err); }); •  参考 –  node.jsの最低限の例外処理 - motsatのブログ –  http://d.hatena.ne.jp/bellbind/20110530/1306764093
  • 54. おわり end

×