Hatena::Bookmark::24Hで使っているPerlモジュールまとめ

ここを作った時の話

http://hatebu24h.ashitano.in
http://hatebu24h.ashitano.in
1時間単位でブックマークを集めたエントリを紹介しているサイトです。

はじめに

http://hatebu24h.ashitano.inを作る際に使用したPerlモジュールをまとめて紹介しておきます。
というか自分が使い方をよく忘れてしまうのでまとめてメモ。
(ソースは一部改変しています)

メールの受信に「Mail::POP3Client」

使い方
use Mail::POP3Client;

my $yaml = YAML::Tiny->read( 'mailsetting.yaml' );
my $pop = new Mail::POP3Client(%{$yaml->[0]});
# 受信したメール分繰り返し
for(my $i=1; $i <= $pop->Count; $i++){
    # header処理
    foreach($pop->Head($i)){
        # 「$_」がヘッダになる。Date:ヘッダをとったりする
    }
    # 本文処理
    foreach($pop->Body($i)){
        # 「$_」が本文になる。リンクを抽出したりする。
    }
    
    # メール消す
    $pop->Delete($i);
}
$pop->Close;
おまけ

http://hatebu24h.ashitano.inでは、「はてなブックマーク お気に入りメール」の受信に使っています。お気に入りメールは自分のGmailアドレスに転送されるようにしています。
Mail::POP3Client()はハッシュを引数にとります。引数中にハッシュをそのまま記述してもよいのですが設定データとしてyamlファイル(ここではmailsetting.yaml)にハッシュの内容を記載&保存しておき、そのファイルをYAML::Tiny->read()で読み込みPOP3Client()にそのまま放り込んでいます。
ちなみに、yamlファイルはこんな感じです

---
USER: xxxxxx
PASSWORD: xxxxxxxx
HOST: pop.gmail.com
DEBUG: 0
USESSL: true

USER:はメールアカウント、PASSWORDはパスワードですね。DEBUG:を1にすればメール受信時、プロンプト上にメールサーバとの詳細なやりとりが表示されるようになります。

設定データの保存・中間データの保存に「YAML::Tiny」

使い方

(書き込み)

use YAML::Tiny;

my $yaml = YAML::Tiny->new;
$yaml->[0]->{$tag}->[$i]->{url}   = $url;
$yaml->[0]->{$tag}->[$i]->{title} = $title;
$yaml->[0]->{$tag}->[$i]->{count} = $count;
$yaml->write( $yamlfilename );

(生成されたYAMLファイルの一部)

---
1231189200:
  -
    comments:
      -
        comment: 'なんていうか、戦隊に、赤黒青ピンクって、やめません? みたいな。 '
        date: 2009-01-06T06:17:49+09:00
        link: http://b.hatena.ne.jp/REV/20090106#bookmark-11543934
        user: REV
      -
        comment: ~
        date: 2009-01-06T06:05:18+09:00
        link: http://b.hatena.ne.jp/kanose/20090106#bookmark-11543934
        user: kanose
    count: 5
    title: 'もうそろそろアニメで突然やってくる女の子とか、幼なじみとか、やめませんか? - 海ノ藻屑'
    url: http://d.hatena.ne.jp/tokigawa/20090105/p1
  -
    comments:
      -
        comment: ~
        date: 2009-01-06T06:15:57+09:00
        link: http://b.hatena.ne.jp/otsune/20090106#bookmark-11543878
        user: otsune
    count: 4
    title: '噂の作られかた: 韓国が海上封鎖されている?'
    url: http://www.cp.cmc.osaka-u.ac.jp/~kikuchi/weblog/index.php?UID=1231161034

(読み出し)

my $yaml = YAML::Tiny->read( $yamlfilename);
foreach $data (@{$yaml->[0]->{$tag}})
{
    $url   = $data->{url};
    $title = $data->{title};
    $count = $data->{count};
}

自分のソースをほぼそのまま書いちゃったので意味がわからないかもしれませんが、配列とハッシュを自由に組み合わせたデータがそのままファイルに保存&読み出しできるといった感じです。
上記の(生成されたYAMLファイルの一部)を見てもらえるとわかりますが、非常に読みやすい形で出力されます。だからYAML大好き。
http://hatebu24h.ashitano.inでは、ブックマークのRSSを解析した中間データの保存やメール設定を別ファイル化するために使用しています。

参考リンク
おまけ

YAML::TinyはTiny.pmというファイル1つで構成されており、他にモジュールを必要としません。スクリプトを実行するフォルダに置いておけば利用できるというフットワークの軽さが魅力です。

Webデータの受信に「LWP::Simple」

使い方
use LWP::Simple;

my $data_from_web = get($url);
if(!defined($data_from_web)){
    # エラー処理
}
# $data_from_webを解析したり

ブックマークのRSSを受信するのに用いています。受信したデータは後述するRSS解析に回すことになります。

RSS解析・RSS生成に「XML::RSS

使い方

(受信したRSSの解析)

use XML::RSS;

my $rss = new XML::RSS;

eval { $rss->parse($data_from_web); };
if($@) {
    # $rss->parse が失敗したときの処理
}

$title = $rss->{'channel'}->{'title'};
foreach my $item ( @{$rss->{'items'}} )
{
    $date     = $item->{'dc'}->{'date'};
    $user     = $item->{'title'};
    $comment  = $item->{'description'};
    $link     = $item->{'link'};
}

perseした後は、配列・ハッシュとして各要素にアクセスしていくことができて便利です。

(配信用RSSデータの生成)

use XML::RSS;
my $rss = new XML::RSS (version => '1.0');
# タイトルっぽいところの生成
$rss->channel(
   title        => '<![CDATA[' . "Hatena::Bookmark::24H(1時間版)" . ']]>',
   link         => "http://hatebu24h.ashitano.in/",
   description  => '<![CDATA[' . "この1時間でもっともブックマークを集めたエントリは何だ?" . ']]>',
);

# content部を使用したい
$rss->add_module(
    prefix => 'content',
    uri => 'http://purl.org/rss/1.0/modules/content/',
);

# 1件のエントリを生成(RSSデータに追加)
$rss->add_item(
   title       => '<![CDATA[' . $title . ']]>',
   link        => $link,
   description => '<![CDATA[' . $contents . ']]>',
   content => {
        encoded => '<![CDATA[' . $contents . ']]>',
   },
   dc => {
     subject  => "",
     creator  => "ashitano",
     date => $datetime,
   },
   mode  => 'insert'
 );
# $rss->as_stringをファイル化してUPLOAD

それぞれの要素にデータを格納して、as_stringでRSSのデータ文字列を取得、アップロードすればOK。

ファイルのアップロードに「Net::FTP

使い方
$ftp = Net::FTP->new($ftpserveradr, Debug => 1);
$ftp->login($ftpaccount,$ftppassword);
$ftp->put($filename);
$ftp->quit;

生成したHTMLファイルやRSSファイルをアップロードするのに用いています。

おまけ

cwd(フォルダ移動)とかdelete(ファイル削除)とかget(ファイル取得とか)もあります。FFFTP(Windowsかよ)みたいなFTPソフトでできることはほとんどできます。
Debugパラメータを1にすることでMail::POP3Clientのように、サーバとのやり取りをアウトプットすることができます。

そんなわけで

RSSを受信して解析→HTMLに加工→それをアップロードみたいなサイトであればこれらモジュールの組み合わせでなんとかなるもんです、という話でした。

次作について

DB・PHPにチャレンジして新サイトを作成中なのですが頓挫し始めています。自宅のクローラで取得したデータをレンタルサーバのDBに叩き込むとかおかしげなことをしています。そろそろ自宅サーバを導入する頃合かもしれませんがGが足りなくてたびびとのふくくらいしか買えない状況です。