2月
25
2010
3

Zen Coding の Perl 実装書きました

今、最高にアツい Zen Coding (ソースは自分) の Perl 実装を書きました。
これがあれば、(今すぐではありませんが) 手に馴染んだ任意のエディタ全てで、Zen Coding を使用することが出来るようになります。
何故かって…?

その種明かしはちょっと後に回しておいて、とりあえずどんなことが出来るモジュールなのかを紹介します。

こうやって実行すると…

use SSSCoding;

print SSSCoding::expand('div') . "\n";
print SSSCoding::expand('a') . "\n";
print SSSCoding::expand('a:mail') . "\n";
print SSSCoding::expand('div#id.class1.class2') . "\n";
print SSSCoding::expand('#head+#body+#foot') . "\n";
print SSSCoding::expand('div#id>ul>li') . "\n";
print SSSCoding::expand('ul>li#id$*5') . "\n";

こう出力されます!

<div></div>
<a href=""></a>
<a href="mailto:"></a>
<div id="id" class="class1 class2"></div>
<div id="head"></div><div id="body"></div><div id="foot"></div>
<div id="id"><ul><li></li></ul></div>
<ul><li id="id1"></li><li id="id2"></li><li id="id3"></li><li id="id4"></li><li id="id5"></li></ul>

本来の Zen Coding には色々な機能がありますが、とりあえず CSS っぽい記述を HTML に展開する機能のみ実装しています。
というか、自分が使いたいのがそこだけなので。

サポートしている識別子は、id を指定する “#”、class を指定する “.”、繰り返しを指定する “*”、繰り返し回数を出力する “$”、子エレメントを指定する “>”、兄弟エレメントを指定する “+” です。
評価順を指定する “()” については実装が面倒だったので未サポートです。書くと変な感じになります。
後述の目的のため、改行などを入れて整形する機能もないので、”()” を使うほど大袈裟な利用はしないだろう、という目論見でもあります。
今後使ってみて、必要を感じたら実装するかも知れません。

また、文法エラーのチェックはしていないため、誤った文法を渡すとメチャクチャな結果になりますが、そこは了承の上で使って下さい。

任意のエディタで Zen Coding を使う

さあ、ここが本来の目的です。
種明かしをすると、この Perl モジュールを使って、ATOK のプラグインを作ればいいのです。
そうすれば、任意のエディタで Zen Coding が利用可能になりますね。

br とか a とか頻繁に使うタグを、辞書登録したことがある人は多いんじゃないでしょうか?
それを動的に行う、超強力版といったイメージです。

もちろんエディタのみならず、ブラウザのテキストエリアでも使えるので、ブログを書く時とか便利かも知れません。
その気になれば、Word でだって Excel でだって利用可能です。

そんなわけで、最終目的は ATOK プラグイン化なのですが、実はまだ出来ていません。
とりあえず Perl 単体で動く状態になったので公開しようと思った次第です。
プラグイン化が完了したらまたアップしたいと思います。

まだ ATOK 16 を使っていてプラグインが使えないので、まずは ATOK のバージョンを上げないと…。

ダウンロード

SSSCoding.pm

ライセンス

ライセンスは MIT License (日本版 wikipedia の項) で公開します。

その他

Perl で実装しているので CGI にもしやすいかと思います。ウェブサービスを作ってみてもいいですね。
あるいは PHP とか、他の言語への移植も簡単では無いでしょうか。ニーズはさておき。

SSSCoding.pm の中で、閉じタグを使わないエレメントは、%SSSCoding::SINGLES で、各エレメントに追加する属性については、%SSSCoding::ATTRS で定義されています。
必要に応じて修正して使って下さい。

モジュール名について

Zen Coding を名乗るには実装が中途半端ですし、名前がぶつかって何らか問題になるのも嫌だったので、モジュール名自体は全く別の名前にしました。
“Style Sheet” Style Coding の略で、SSSCoding としています。

Written by Otchy in: Development | タグ: ,
7月
26
2009
3

Twitter ボットの作り方 Perl 編 (目次)

一通りの連載が終了したので、最後になりますが、各エントリに簡単な説明を付けた目次を別エントリとしてあげておきます。

  • Twitter ボットの作り方 Perl 編 (1)
    ボット作成の前提となる基本的な機能の動作確認を行います。この部分がうまくいかない場合、そもそもボットを作成する環境が整っていない事になるので重要です。
    • 前書き
    • 目標
    • 用意するもの
    • 方針
    • 下準備
  • Twitter ボットの作り方 Perl 編 (2)
    単にランダムにつぶやくだけの簡単なボットを作ります。cron に登録することで本当の意味でボットとして活動可能になります。
    • 状態ファイルの準備
    • データの準備
    • 実際のスクリプト
    • cron への登録
  • Twitter ボットの作り方 Perl 編 (3)
    Twitter 検索を組み合わせて、ボット宛のつぶやきを処理する方法を解説します。このテクニックは様々なタイプのボットで応用出来ます。
    • ボット作成の方針
    • 設定ファイルの追加
    • 状態ファイルの準備
    • 実際のスクリプト
    • 動作サンプル
    • 改造のヒント
    • 実は…
  • Twitter ボットの作り方 Perl 編 (4)
    Web 上に公開されている RSS を元につぶやくボットを作ります。このスクリプトのままでも、元になる RSS さえ工夫すれば、それだけで多彩なボットに化けさせる事が出来ます。
    • CPAN ライブラリの追加
    • 設定ファイルの準備
    • 実際のスクリプト
    • その他の注意点
  • Twitter ボットの作り方 Perl 編 (5)
    Web 上で公開されている外部 API を使用した例です。ここでの例は実用性があまり無いですが、ボットの可能性の広がりを感じてもらえればと思います。
    • CPAN ライブラリの追加
    • アプリケーション ID の取得
    • 設定ファイルの準備
    • 実際のスクリプト
    • あと書き
Written by Otchy in: Development | タグ: ,
7月
26
2009
3

Twitter ボットの作り方 Perl 編 (5)

Twitter ボットの作り方解説第 5 弾。ボットに対してのつぶやきを検索して、検索結果を返信するボットを作ってみます。
以下は、第 4 弾までの状態を前提としています。

さて、当初の予定だと Google 検索を行った結果を返すボットを作ろうとしていたのですが、Google 検索 API は公開をやめてしまっているのですね。知りませんでした…。
こういう時は Yahoo の出番という事で、代わりに Yahoo 検索の結果を返すボットを作ります。
Yahoo の様々な公開 API 群は、Google の後追いで公開を始めただけあって優れたものが多いのですが、いかんせん Google の陰に隠れがちですね。

CPAN ライブラリの追加

例によって、Yahoo 検索を便利に実行するためのライブラリが CPAN に登録されているので、インストールしておきます。

$ su -
# perl -MCPAN -e shell
cpan> install Yahoo::Search

アプリケーション ID の取得

Yahoo の検索 API を使うためには、あらかじめアプリケーション ID というものを取得する必要があります。
Yahoo のアカウントを持っていれば、簡単に取得出来るので、以下のサイトからあらかじめ取得しておきます。
Yahoo! デベロッパーネットワーク

大手のウェブサービスで API を公開している場合、「API キー」とか、「デベロッパー ID」とか、呼び方はそれぞれですが、大抵はのこアプリケーション ID のようなものが用意されています。
これらの ID は、各 API が過剰に利用されていないかを監視したり、必要に応じて利用を止めたりする目的で用意されています。
とはいえ、Yahoo 検索のケースで、1日あたり 5000 回とかなので、普通の個人が利用する分には制限についてさほど気にする必要はありません。

設定ファイルの準備

今回作成するボットは、第 3 弾で作った特定ワードに返信するボットと、基本的な作りは一緒です。
設定には前述のアプリケーション ID を追加し、最後のつぶやきの管理には、sinceId を使います。

config.yml

username: "your_twitter_user_name"
password: "your_twitter_password"
appId: "your_yahoo_application_id"

status.yml

sinceId: 0

実際のスクリプト

#!/usr/bin/perl

# 使用するモジュールの読み込み
use strict;
use warnings;
use Encode;
use FindBin;
use YAML::Tiny;
use Net::Twitter;
use Yahoo::Search;

# yml ファイルの読み込みと、Twitter モジュールの初期化
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 $username = $config->{'username'};
my $appId = $config->{'appId'};
my $sinceId = $status->{'sinceId'};

# Twitter 検索。to: オプションでボット宛のつぶやきすべてを取得
my $response = $twit->search({q => 'to:' . $username, since_id => $sinceId});

# Twitter 検索結果を 1 件ずつ処理
for my $result ( reverse( @{$response->{'results'}} ) ) {
    my $query = Encode::encode('utf8', $result->{'text'});
    my $fromUser = $result->{'from_user'};
    my $statusId = $result->{'id'};

    # ボット宛の @ 部分を取り除く
    $query =~ s/\s*\@${username}\s*//;

    # Yahoo 検索 (最大5件、日本語圏で検索)
    my @results = Yahoo::Search->Results(
        Doc => $query,
        AppId => $appId,
        Count => 5,
        Language => 'ja'
    );

    # Yahoo 検索結果を 1 件ずつ処理
    for my $page (@results) {
        # ボットに対するつぶやきへの返信
        my $reply = '@' . $fromUser . ' ' . $page->Title . ' ' . $page->Url;
        $twit->update({status => $reply, in_reply_to_status_id => $statusId});
    }
    $sinceId = $statusId;
}

# 最後に処理したつぶやきの ID を保存
YAML::Tiny::DumpFile($FindBin::Bin . '/status.yml', {sinceId => $sinceId});

ここまで作ってきたボットの内容を理解していれば、ほとんど自明のことしか無いかと思います。
Yahoo 検索についても、Yahoo::Search という優れたライブラリがあるので、非常にシンプルに記述出来ています。

あと書き

「Twitter ボットの作り方 Perl 編」の連載はこれで終わりになります。

連載の終盤で、RSS や外部の API を利用するボットを作成しました。
今のウェブ上ではこういった情報発信が広く行われており、複数のサービスを組み合わせることで多彩なボットを作成可能です。
また、スクレイピング等の手法も組み合わせれば、まさにその組み合わせはアイディア次第。無限の可能性があると言っていいでしょう。
もちろん、一発ネタのボットで注目を集めるというのも面白いそうです。

この連載が、そんな素敵ボットを作ろうとする方の一助となれれば幸いです。

Written by Otchy in: Development | タグ: ,
7月
19
2009
2

Twitter ボットの作り方 Perl 編 (4)

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: "http://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 検索をするボットを作ってみます。

Written by Otchy in: Development | タグ: ,
7月
16
2009
2

自分のサイトの合計はてブ数を淡々と csv に記録し続ける

Twitter ボットの作り方 Perl 編 連載中ですが、ちょっとお休みして、さっき思い立って書いたスクリプトを紹介します。

最近、TopHatenar の更新が止まってしまっていて悲しいので、自分のサイトのトータルはてブ数を記録して、自分でグラフを書くことにしました。
といっても、自分が見る専用で問題ないので、csv を出力しておくだけです。適宜 Excel とかで加工してグラフ化します。

まず必要になる CPAN モジュールをインストールします。root 権限必須です。

$ su -
# cpan
cpan> force install XMLRPC::Lite
cpan> install DateTime

XMLRPC::Lite は自分の環境だとテストで引っかかって上手く入らなかったので、force install してます。
force install する前に、通常の install で入れられないかを試すべきです。
いずれのインストールも結構時間がかかるので、原則放置でたまに Enter を押してやる感じです。

実際のスクリプトは下記のような感じです。
標準出力に吐くようにしたので、ファイルに記録したい場合は任意にリダイレクトしてやります。

#!/usr/bin/perl

use strict;
use warnings;
use XMLRPC::Lite;
use DateTime;

my $url = 'http://www.otchy.net';

my $count = XMLRPC::Lite
    ->proxy('http://b.hatena.ne.jp/xmlrpc')
    ->call('bookmark.getTotalCount', $url)
    ->result;

my $now = DateTime->now(time_zone => 'Asia/Tokyo');
print $now->strftime('%Y-%m-%d') . ',' . $count . "\n";

$url の値はカウント対象の URL ですが、もちろん変更して下さい。
スクリプトに実行権限を与えて実行すると、こんな感じの出力が出てきます。

2009-07-16,204

毎日の記録を残すのであれば、例えば下記のように cron に登録すればいいです。

00 00 * * * /home/your_id/hatebulog/hatebulog.pl >> /home/your_id/hatebulog/hatebulog.csv

今のところ日次で記録する前提で日付しか出力していませんが、はてブ数が多くもっと頻繁に記録するのであれば、出力を下記のように変える事で実行時間も記録されます。

print $now->strftime('%Y-%m-%d %H:%M:%S') . ',' . $count . "\n";

最初に自分専用とはいったものの、いったん csv に落としてしまえば、PHP + Google Chart API でグラフ化して Web から見れるようにするとかもありですね。

追記(2009-08-04)

グラフ化してみました!

Written by Otchy in: Development | タグ: ,

Powered by WordPress | Aeros Theme | TheBuckmaker.com