Más contenido relacionado
Title
- 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 ̄ ̄〉 ̄〉
 ̄ ̄ ̄ ̄
- 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);
- 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
- 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
- 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
- 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;
}
}
});
- 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);
});
- 43. ② 大変な方法
• C/C++ でモジュールを書く
– 面倒ですが作れば速いです
• v8 のお作法に従って書けばOK
• 詳しく解説しようとすると時間足りない
ので、詳細は以下をご参照下さい m(_ _)m
• node.js の mecab addon 作った - 凹みTips※
– http://d.hatena.ne.jp/hecomi/20120611/1339347112
※ ここでは node-waf をコンパイルツールとして使っていますが、最近は node-gyp に置き換わったみたいです。
- 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 あたりがおすすめです。
- 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