Home JavaScript Greasemonkey PHP

Twitter ボットの作り方 Perl 編 (4)2009-07-19


Twitter ボットの作り方解説第 4 弾。特定の RSS の内容をつぶやき続けるボットを作ってみます。
以下は、第 3 弾までの状態を前提としています。

CPAN ライブラリの追加

これまでは、通信する先として Twitter サービスにしか通信していなかったので、Net::Twitter モジュールだけで済んでいましたが、さらに外部の RSS を取得するために CPAN ライブラリを追加します。
例によって各種設定は、特に必要のない限りすべてデフォルト (そのまま Enter) で構いません。
インストールに時間がかかるのでしばし待ちましょう。

$ su -
# perl -MCPAN -e shell
cpan> install XML::FeedPP

Perl 上で RSS を扱うライブラリというと、XML::RSS が有名なのですが、今回は Atom フィードも同等に扱いたかったので XML::FeedPP を採用しました。
RSS と Atom についての関係はこのあたりを参照してみて下さい。
よく分からなければそんなに気にしなくて構いません。
(正確に表現するなら RSS と Atom を合わせてフィードと呼称すべきですが、あえてここでは一般的な名称として RSS という呼称を使用しています。)

設定ファイルの準備

これまでと同じように、config.yml と status.yml を使います。今回はそれぞれ下記のような感じです。

config.yml
username: "your_twitter_user_name"
password: "your_twitter_password"
source: "https://www.otchy.net/feed/rss/"

status.yml
lastHash: ""

source はもちろん接続先 RSS のアドレスですね。
lastHash は最後につぶやいた RSS アイテムのハッシュ値を記録します。
なぜこのようなものが必要になるかというと、RSS や Atom のフォーマットには様々な種類があり、唯一のアイテムを指定する ID のようなものが必ずしも提供されないからです。
従って、複数の値を組み合わせたハッシュ値を用いて、それを元に最後のつぶやきを管理します。

実際のスクリプト

#!/usr/bin/perl

# 必要なライブラリの読み込み
use strict;
use warnings;
use Encode;
use FindBin;
use YAML::Tiny;
use Net::Twitter;
use XML::FeedPP;
use Digest::MD5;

# 各種設定値の取得
my $config = (YAML::Tiny->read($FindBin::Bin . '/config.yml'))->[0];
my $status = (YAML::Tiny->read($FindBin::Bin . '/status.yml'))->[0];
my $twit = Net::Twitter->new(username => $config->{'username'}, password => $config->{'password'});
my $source = $config->{'source'};
my $lastHash = $status->{'lastHash'};

# RSS の読み込み
my $feed = XML::FeedPP->new($source);

# 最後につぶやいた RSS アイテムより新しい RSS アイテムを調べる
my @updates;
for my $item ($feed->get_item()) {
    my $hash = &calcHash($item);
    last if $hash eq $lastHash;
    # 配列の頭から詰めていく事で、つぶやきの順番を RSS と逆にする
    unshift(@updates, $item);
}
# RSS の内容を順につぶやく
for my $item (@updates) {
    my $update = $item->title() . ' ' . $item->link();
    $twit->update($update);
    $lastHash = &calcHash($item);
}

# 最後につぶやいた RSS アイテムのハッシュ値を保存
YAML::Tiny::DumpFile($FindBin::Bin . '/status.yml', {lastHash => $lastHash});

# RSS からハッシュ値を計算する
sub calcHash {
    my $item = shift;
    my $id = $item->guid();
    my $url = $item->link();
    my $title = $item->title();
    my $pubDate = $item->pubDate();
    my $hashKey = '';
    $hashKey .= $id if $id;
    $hashKey .= $url if $url;
    $hashKey .= $title if $title;
    $hashKey .= $pubDate if $pubDate;
    return Digest::MD5->md5_hex($hashKey);
}

第 3 弾までの内容を把握していれば、そんなに目新しい部分は無いかと思います。
ポイントとなるのは、今回 CPAN からインストールして読み込んだ XML::FeedPP と、Digest::MD5 でしょう。

XML::FeedPP は、RSS や Atom の読み書きをするためのライブラリで、RSS の複数のバージョンおよび Atom を透過的に扱う事が出来る優れものです。
大抵のサイトで用意されている RSS (Atom) であれば、ライブラリ任せで上手く読み込む事が出来ます。
RSS のバージョンなどにかかわらず、共通の方法で情報を取得できるのが楽でいいですね。

Digest::MD5 は、Perl 標準のモジュールで、MD5 形式のハッシュ値を計算するためのものです。
ハッシュ値の元になる文字列には、タイトルや URL 等を連結した文字列を使っています。
なので、その文字列自体をそのままキーとして使用してもいいのですが、見栄えが良くないので MD5 化したものをハッシュ値としています。

また、ハッシュ値の計算には、guid、URL、タイトル、更新日時の全てを使っているため、そのいずれかが変更されただけで別の投稿として認識されてしまいます。
そのことの都合が悪い場合、例えば URL だけで同一性を判断するなど、条件を調整してみてください。

その他の注意点


cron の間隔は、RSS が更新される間隔に合わせて適宜調整して下さい。通常は 30 分間隔くらいが適当ではないでしょうか。
なお、配信される RSS ファイルが UTF-8 であることを前提としています。もし異なる文字コードで配信されていたら、つぶやく前に変換をしないといけないですが、UTF-8 以外の RSS ってあまり聞いたことが無いので大丈夫だと思います。

このくらいまで出来るようになると、かなり実用的なボットが作成可能ですね。
自分の欲しい RSS だけをマージして、フィルタリングした結果の RSS を Yahoo! pipes で作ってボットにつぶやかせるとか、応用の幅が広いです。
次の 第 5 弾で、一応本連載は完了します。最後は外部のウェブサービスと連携する例として、Google Yahoo 検索をするボットを作ってみます。


カテゴリ: Development タグ: twitter perl