PerlとRubyがくしゅう帳

プログラミングの勉強会の参加記録や学んだことなど。 twitter ID : @tomcha_です。 最近は主にPerl関連の勉強会やコミュニティに参加しています。

2013年07月

perl徹底攻略の本を買いに行った時、並んでおいてあったweb開発の基礎徹底攻略が初心者には良い感じの本だったので購入し、こちらから読み始めました。

プログラミング言語(スクリプト言語)を学んで、色々webアプリを作るとなると、プログラミング言語以外にも色々な必要な知識が必要なことがわかってきた自分にとって、この本は超初歩的なことから解説してあるとても良い本です。(まだ読み始めたところですが)

perl入学式に入学するまでは、「perlってcgiとかいう掲示板つくるやつですよね?」的な非常に誤った認識をしていたので、cgiについて理解を深めるためにサンプルコードを試してみた。(P11 リスト1 ちなみに、リスト1の最後の行にヒアドキュメントの終端記号EOFを書かないと動きません。ミスプリ?)

まずは、MacbookAir単体でwebサーバーApacheを起動してCGIを試せる環境を設定。

参考にしたサイトはこちら

まず、MacOSX Mountain LionでApacheを使う為には、ターミナルからCUIで設定するしか方法が無いらしい。ターミナルで sudo -s コマンドでスーパーユーザーになって、apacheの設定ファイル

/etc/apache2/httpd.conf

を編集。

自分の環境では、ApacheからCGIが使えるようになる設定文

#AddHandler cgi-script .cgi

が397行目にあったので、#を消して有効にする。

自分のホームディレクトリに置いた実験用cgiファイルを実行できるように、

/etc/apache2/users/ユーザー名.conf

を編集。options の行末にExecCGIを追記。

Apacheの起動、停止、再起動はスーパーユーザー権限でターミナルで以下のコマンドを打つ。

apachectl start

apachectl stop

apachectl restart

ホームディレクトリ/sites/ の中にcgiのサンプルコードを置き、ファイルのパーミッションを755に変更、そしてブラウザからlocalhost/~ユーザー名/サンプルコード.cgiにアクセスすると、ブラウザにperlのコードの実行結果がきちんと表示されました。

今回学んだCGIの使いかた

・perlのコードのファイル名を.plではなく、.cgiにする。

・print命令で標準出力に出力されたhtmlを記述したテキストデータが、cgi -> webサーバ を通じて、クライアントのブラウザにhtml形式で返され、表示される。

cgi、ちょっとしたスクリプトなら、コードを書く手間は非常に楽。ブラウザで結果を手軽に確認できるのでこれはこれで面白かった。

ちょっとした実験なら、cgiも便利。

ある日、リスペクトしている、とある偉いperlハッカー先生がツイッターでつぶやいていた。

twitter

perl入学式で、無いものはcpanモジュールを駆使して自分で作れば良いと教わっていたので、自分でtwitterbotを作って見ることにした。

・・・何ヶ月か前に勉強会perl鍋に参加した時に作り、ローカル環境で実験してうまく動いてからずっと放置していたので、きちんとスクリプトを仕上げてさくらvpsのサーバーに上げて自動実行させようとしたら色々ハマッてしまったので、その解決策を備忘録として書いておく。


twitterbotのスクリプトは、cpanのNet::Twitter::Lite::WithAPIv1_1モジュールを使った。TwitterAPIの利用登録から実際の使い方は@yusukebeさんのブログ記事「イカ娘でTwitter OAuth認証」を参考にさせていただいた。


作ったtwitterbotは、

@で話しかけられると定型文を返すというbotなので、perlのスクリプトでは、@で話しかけれられているかを取得->話しかけられていれば、@で返す

の部分を作り、その.plファイルをcronという定期的にスクリプトを実行してくれるデーモンで5分毎に実行させるような仕組みにした。


cronの設定は、crontab -eというコマンドで以下の書式で設定ファイルを書く。

PATH=/home/ユーザー/perl5/perlbrew/bin:/home/ユーザー/perl5/perlbrew/perls/perl-5.16.3/bin

*/5 * * * * /home/ユーザー/ディレクトリ/スクリプト.pl


注意点は、PATHで使うperlの位置を設定しておかないと、デフォルトで入っているシステムのperlで実行しようとしてしまうので、perlbrwでインストールした新しいperlを使うには、PATHを設定する。

で、いざcronを実行してみると、5分毎にスクリプトの実行を試みているが、エラーが帰ってきてスクリプトが動いていない。エラーの内容は、

Can't locate JSON.pm in @INC (@INC contains: ・・・

cpanモジュールが然るべき位置に無いと怒られた。


cpanm -reinstallコマンドでインストールしなおしてもエラーは変わらず。

エラーの出てるcpanモジュールのuse宣言の順番を最後に回すと、一番最初にuseしているモジュール名で同様のCan't locate エラーが出た。どうも全てのcpanモジュールが読み込めてない様だ。


色々ググってこちらのブログ記事「PerlによるTwitter bot制作」を参考にさせていただいた。

どうやら、crontabで設定したPATHは、使用するperlのディレクトリ位置情報のみで、インストール済みのcpanモジュールのディレクトリ位置情報は別の模様。cpanモジュールの位置は、フルパスで指定しなければならない様だ。


cpanモジュールの絶対パスをスクリプトの最初に記述、FindBinというcpanモジュールで、現在実行している.plスクリプトのディレクトリ位置を取得し、スクリプト中に出てくる設定ファイル等のディレクトリ位置を読み込めるように設定しなおしたら、twitterbotのスクリプトは見事動いた。


完成したbotはこちら。何かやらかしてしまった時に、@dakarabot にメンションを飛ばすと反応します。


twotterbotを作ってみて、困った点

  • twitterのAPIの制限で、同じツイートは短時間の間にツイートできない。(スパム対策か?)だから、スペースをかましたダミーのツイートとかをいくつか作って誤魔化してみた。だから、大量に@が飛んでくると、多分動かない。
  • 自分には絵心が全く無いので、twitter用アイコンの作成ができませんでした。なので、偉いperlハッカー先生の趣向を尊重してみた。

perlでsqlite3で作成したDBに接続するコードを書いてテストしてみました。

  • 参考にした本
    • perl鍋で使っていたcpanモジュールガイドで、DBIのページを参考にスクリプトを書いてみました。
  • 準備
    • あらかじめ、MACにデフォルトで付属しているデータベース、SQLIte3でデータベースとテーブル定義、サンプルレコードを作っておく。
  • やった事
    • DBIをcapnからインストール。
  • 書いたコード
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use DBI;
use Data::Dumper;

my $db = DBI->connect('dbi:SQLite:../database/gakusyuu.db','',''); 
 print Dumper $db;

接続文字列の引数に今回の実行環境、'dbi:SQLite;dbname=DBのパス/DBのファイル名'を設定して実行してみたところ・・・

=> install_driver(SQLite)と怒られる。DBD::SQLite等の各データベースに接続する為のドライバモジュールは別でインストールする必要があるみたい。cpanからDBD::SQLiteをインストールして、もう一度実行。

=>DBIのオブジェクトのハッシュが返されたので、とりあえず成功?

続きのテストコードをサンプルに習って書いてみた。

my $st = $db->prepare('select * from type');
$st->execute();
while (my $row = $st->fetch row){
	print Dumper $row;
} 

コードの内容を自分なりに整理。

  1. DBI->connect()でデータベースに接続するオブジェクトを生成する
  2. 上記データベース接続オブジェクトのprepare()メソッドで、引数のSQL文を実行する事ができる、SQL命令オブジェクトを生成。
  3. 上記SQL命令オブジェクトのexecute()メソッドを実行し、SQL文の実行結果(今回はselect文)がSQL命令オブジェクトに格納される。
  4. 上記SQL命令オブジェクトに格納された実行結果は、fetchrow_hashrefでワンレコードごと取り出す事が可能。while文で$row変数にワンレコードずつ取り出してプリントしてみた。

{'フィールド名1'=>'データ',

'フィールド名2'=>'データ'

}

の形式のハッシュ(リファレンス)の取り出しに成功。

なんと、めっちゃ簡単に接続してレコードが取り出せてしまった!cpanモジュール、すごい。

※今回の疑問

データベース本体は、どのディレクトリに入れるのが定石?

※格納されるとか、生成するというのは、それぞれデータ等の場所への参照が格納されているイメージを脳内で補完しておくとイメージしやすいかな?

このページのトップヘ