phpでtwitterのbotを作る(TLに反応修正版)
昨日の記事の続きです。
TLの特定語句に反応するが、@付きのpostとRTには反応しない、という修正点。あと、eregからpreg_matchw使うように。
とりあえずソース
<?php $username = ""; $password = ""; //最新のTLのステータスIDを保存しておくファイルです。パーミッションは書き込み可に。 $filename = "./tmp/last.dat"; //過去の開いて取得 $fp = @fopen($filename,'rb') or die("ファイルが開けません"); flock($fp, LOCK_EX); $line = fgets($fp, 64); fclose($fp); //自分がフォローしているfriendsのリストです。 $host = "http://twitter.com/statuses/friends_timeline.xml"; //ユーザーの発言一覧 //一番最初の時やファイルが壊れた時、最新1件のみ発言を取得する if(!empty($line)){ $last_id=$line; $host .="?since_id=".$last_id; } else{ $host .="?count=1"; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $host); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); $result = curl_exec($ch); curl_close($ch); $XML = simplexml_load_string($result); $i = count($XML)-1; $j = 0; while($i >= $j) { $var = $XML->status[$i]->text; $reply_name = $XML->status[$i]->user->screen_name; $name = $XML->status[$i]->user->name; if($reply_name != $username){ if( !preg_match ( "/@[a-zA-Z0-9-_]{3,}/", $var ) ){ if( preg_match ( "/おやす|寝る/u", $var )){ $message = "@".$reply_name." おやすみ!"; tweet($message ,$username,$password); } if(preg_match ( "/おはよ|むくり/u", $var )){ $message = "@".$reply_name." おはよう!"; tweet($message ,$username,$password); } if(preg_match ( "/ただいま/u", $var )){ $message = "@".$reply_name." おかえり"; tweet($message ,$username,$password); } } } $i--; } //ファイルに最新id書き込み $last_id = $XML->status[0]->id; $dat = (string)$last_id; file_put_contents($filename,$dat,LOCK_EX); //ポスト部分の関数 function tweet($message ,$username,$password) { $message =urlencode($message); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://twitter.com/statuses/update.xml'); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "status=$message "); curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); $buffer = curl_exec($ch); curl_close($ch); } ?>
解説です。
if( !preg_match ( "/@[a-zA-Z0-9-_]{3,}/", $var ) ){
ここで、@[スクリーンネーム]の入った発言か否か、判断しています。
正規表現でまず先頭に@があって、そのあと中カッコ[]で囲ったa-zA-Z0-9と続きます。
中カッコは範囲なんですね。後、ハイフンとアンダーバーも使われる(ん?ハイフン使えたっけ?
つまり半角英数プラス-_。
その後に来てるのが大カッコ{}、数字の3、カンマ(,)と来てる。これは前の半角英数とかが3回続くって意味ですね。
ユーザーネームでとれる最小の字数が3っぽいので。
これで、文中に@[スクリーンネーム]のがあるか否か判定できますね。
ちなみにRTも考えていたのですが、RTにはたいがいこの@[スクリーンネーム]がついてきますから、RTのはわざわざ記述しなくても大丈夫でしょう。
次に、preg_matchです。
if( preg_match ( "/おやす|寝る/u", $var )){
ここで前のeregと違うのはエスケープ/の存在と、末尾のアルファベットu、区切りの|。
エスケープは前も書いたので、今回はその後にあるu。
こちらの記述が詳しいです。
http://ifs.seesaa.net/article/26300967.html
preg系の正規表現にパターン修飾子「u」を指定すると、パターン文字列がUTF-8でエンコードされた文字列として扱われるようになります
twitterの文字コードはutf-8、このスクリプトも当然utf-8で書かれているのですが、あってるはずなのにマッチしない状態が長く続いて。
なんでかな?って疑問がずっとあったんです。(それで苦手だったってのもあるかも)
このやり方で氷解しました。
最後の区切り|ですが、勘のいい方ならわかると思いますがorみたいなものですね。
おやす、寝る、どちらが来てもマッチするということです。ちなみにカッコはつけてもつけなくても動作一緒でした。
違いがいまいちわからないんですが、併用する時とかだけですかね。スミマセン。詳しい方指摘してくださると嬉しい…(人任せ)
今までの言葉に反応する系のスクリプトも、書き換えたり自分なりに書いてみるのも一興だと思います、是非そうしてください。
正規表現は本当に奥が深いです。使いこなせばbotは精巧になるでしょうし、それ以外にも効率がよくなるでしょうね。
私も勉強していきます!