大西ブログ

All your blog are belong to us

喰らえ10年鍛えた俺の test.pl !!

こんにちは、2011年くらいにディレクターになってめっきりPerl書かなくなった id:onishi です。

この記事は Perl5 Advent Calendar 2015 18日目です!

書き捨てのコードを test.pl という単一ファイルに __END__ と共に上に追加し続けて10年。3万行超に成長した俺の test.pl から厳選したコード群を喰らえ、という主旨の記事です。

今日のお品書きはこんな感じです。

( [PR]この目次ははてなブログの目次機能で自動生成しています )

ちなみに、書き捨てのコードから良いものは、プロジェクトのリポジトリに入れたり、~/bin/ に置いたりしています。今日は ~/bin/ に移った厳選処理も紹介しますね。
とにかく test.pl にいろんな処理が書かれているので、日付処理したい、とかメール送りたい、とか思ったらそれっぽい単語でファイル内を検索すると適切なコードスニペットが見つかるので業務効率に繋がっています。

list()

ORM使うほどでもないけどさくっとDB引きたい時の簡易DBIラッパーです。

use DBI;

my $host = {
    user => ['host1', 'user', 'pass'],
    blog => ['host2', 'user', 'pass'],
};

sub dbh {
    my $dbname = shift;
    DBI->connect_cached(
        sprintf(
            'dbi:mysql:database=%s;host=%s',
            $dbname,
            $host->{$dbname}->[0],
        ),
	$host->{$dbname}->[1],
        $host->{$dbname}->[2],
    )
}

sub item {
    my $list = list(@_) or return;
    $list->[0];
}

sub list {
    my ($dbname, $sql, @bind) = @_;
    my $dbh = dbh($dbname);
    my $sth = $dbh->prepare_cached($sql);
    $sth->execute(@bind);
    return $sth->fetchall_arrayref({});
}


こんだけ書いておけば list() と item() で以下みたいなコードが書けます。

my $user = item(
    user => 'SELECT * FROM user WHERE name = ?',
    'onishi'
);

my $entries = list(
    blog => 'SELECT * FROM entry WHERE user_id = ?',
    $user->{user_id},
);

print map { $_->{title} . "\n" } @$entries;

数クエリで済みそうな集計を雑にしたい時に使ってます。

fotolife

フォトストレージサービスはてなフォトライフに簡単にファイルをアップロードするコマンドです。Config::Pit で username, apikey, folder を指定しておきましょう。

$ fotolife ファイル
$ fotolife URL

第一引数にファイルパスかURLを受け取り、自分のフォトライフにアップロードし、アップロード結果を出力します。
結果はこのように、はてなブログ用記法、はてなダイアリー用記法、フォトライフpermalink、画像permlinkをまとめて出力する親切設計です。

$ fotolife some-file.jpg
[f:id:onishi:00000000000000p:plain]
[f:id:onishi:00000000000000p:image]
http://f.hatena.ne.jp/onishi/00000000000000
http://cdn-ak.f.st-hatena.com/images/fotolife/o/onishi/000000/00000000000000.png
#!/usr/bin/env perl
use strict;
use warnings;

use Config::Pit;
use FileHandle;
use LWP::Simple 'get';
use XML::Atom::Entry;
use XML::Atom::Client;

my $file = shift;

my $type = $file =~ /(png|gif|bmp)$/i ? lc($1) : 'jpeg';
my $t    = substr($type, 0, 1);
my $ext  = $type eq 'jpeg' ? 'jpg' : $type;
   $type = "image/$type";

my $image;
if ($file =~ m{https?://}) {
    $image = get($file);
} else {
    local $/; # slurp mode
    my $fh = FileHandle->new($file) 
        or die "cannnot open $file: $!";
    $image = $fh->getline;
}

my $config = pit_get("hatena.ne.jp", require => {
    username => 'username',
    apikey   => 'apikey',
    folder   => 'folder',
});
my $username = $config->{username};
my $apikey   = $config->{apikey};
my $folder   = $config->{folder};

my $PostURI = 'http://f.hatena.ne.jp/atom/post';

my $api = XML::Atom::Client->new;
$api->username($username);
$api->password($apikey);

my $entry = XML::Atom::Entry->new;
$entry->content($image);
$entry->content->type($type);
$entry->title('');
my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/');
$entry->set($dc, 'subject', $folder) if $folder;
my $EditURI = $api->createEntry($PostURI, $entry) or
  die $api->errstr;

$EditURI =~ /(\d+)/ or die $EditURI;
my $fototime = $1;
my $initial  = substr($username, 0, 1);
my $date     = substr($fototime, 0, 8);
print "[f:id:$username:$fototime$t:plain]\n";
print "[f:id:$username:$fototime$t:image]\n";
print "http://f.hatena.ne.jp/$username/$fototime\n";
print "http://cdn-ak.f.st-hatena.com/images/fotolife/$initial/$username/$date/$fototime.$ext\n";

長い。あと、WSSE認証使ってますけど最近はOAuthでも書けます。
はてなフォトライフAtomAPI

wq

みんな大好き、Web::QueryjQuery ライクに scraping できます。

#!/usr/bin/env perl
use strict;
use warnings;

binmode STDOUT, ':utf8';

use Web::Query;

my $url      = shift or die;
my $selector = shift or die;
my $limit    = shift || 0;

my $i;
wq($url)->find($selector)->each(
    sub {
        printf("%s\n", $_->text);
        $limit && ++$i >= $limit and exit;
    }
);

こんな雑なスクリプトを wq という名前でPATHが通ったところに用意しておくと、URLとセレクタを引数にこんな感じで簡易スクレイピングコマンドとして使えます。

$ wq http://www.hatena.ne.jp 'ul#servicelist li' 5
    ブックマーク ネット上にお気に入りを保存できるサービス。ネット上の旬な話題がすぐわかる
    ブログ 書き残そう、あなたの人生の物語。だれでも使いやすく簡単に書ける、はてなの新しいブログ
    B!KUMA “がんばる私”に、ちょっと一息。恋愛、レシピ、おしゃれ、育児など女性が気になる話題をお届け
    ニュース ネットで旬な話題を分かりやすく紹介。地元発の京都情報、ひとこまマンガも楽しめるニュースサイト
    人力検索 調べたいことを誰かが自分の代わりになって調べてくれる人力検索サービス

(はてなトップページから「はてなのサービス」を5件取得する例)

セレクタ指定して取得した数字を別のサービスに投げたりすると便利なんじゃないでしょうか。

punycode

日本語ドメインでイラッとすることが多いので punycode の自動変換をします。

#!/usr/bin/env perl
use strict;
use warnings;

use IDNA::Punycode;
use Encode;

binmode STDOUT, ':utf8';

idn_prefix('xn-');

my $word = shift;

if ($word =~ /^xn-/) {
    print join('.', map { decode_punycode(Encode::decode('utf-8', $_)) } split(/[.]/, $word)) . "\n";
} else {
    print join('.', map { encode_punycode(Encode::decode('utf-8', $_)) } split(/[.]/, $word)) . "\n";
}

こんな感じ。

$ punycode xn--wgv71a119e.jp
日本語.jp

$ punycode 日本語.jp
xn--wgv71a119e.jp

イラッとしなくなりました。

statuscode

任意のステータスコードを返すサーバーをさっと建てたいこと、ありますよね!(無い)

#!/usr/bin/env perl
use strict;
use warnings;

use HTTP::Daemon;
use HTTP::Status;
use HTTP::Response;

my $d = HTTP::Daemon->new(LocalPort => shift || undef) || die;
print "Please contact me at: ", $d->url, "\n";
while (my $c = $d->accept) {
    while (my $r = $c->get_request) {
        if ($r->method eq 'GET' and $r->url->path =~ m{/(\d+)}) {
            my $code    = $1;
            my $header  = HTTP::Headers->new( 'Content-Type' => 'text/html' );
            my $message = status_message($code) || '';
            my $res     = HTTP::Response->new(
                $code,
                $message,
                $header,
                "<title>$code $message</title><h1>$code $message</h1>"
            );
            $c->send_response($res);
            warn "$code $message\n";
        } else {
            $c->send_error(RC_FORBIDDEN)
        }
    }
    $c->close;
    undef($c);
}
$ statuscode
Please contact me at: http://localhost:53812/

サーバーが立ちます。
http://localhost:port/200 のように任意の数字をパスに指定するとその数字のステータスコードを返します。なんか便利ですね!

結びの言葉

10選くらい挙げたかったのですが、意外と仕事のコードと密なコードが多すぎて紹介できなくて飽きてきたのでここらへんで終わります。
1ファイルを眺めるだけで10年の歴史が眺められて面白かったです。

僕とはてなと開発合宿

はてなスタッフアドベントカレンダー2015 を始めます!

はてなスタッフアドベントカレンダー2015 - はてなスタッフアドベントカレンダー

というわけで初日は私、 id:onishi がつとめます。今日から25日間、スタッフによりなんからの「はてな」に関するエントリーが続く予定ですのでお楽しみに!

初日ということで何を書こうかなと思いましたが、今日は「僕とはてなと開発合宿」について書いてみます。

はてなの開発合宿の歴史

はてなで初めて開発合宿は2005年の事でした。皆さんご存じ「はてなブックマーク」は合宿で産声を上げました(ここらへんに詳しい)。
その後数年は、「少人数で新サービスを作る合宿」というのを行っていました。当時の新サービスは合宿ドリブンで作られたものが多いです。

最近のはてなは開発者の人数も増えたため、たくさんの人数で出かけるイベント型の合宿を行っています。チームを組んで2泊3日で、各チームの成果を発表するという流れです。
去年行われた合宿をもとに、合宿の企画・運営について記事を書きましたので、そちらに詳しいです。

また、合宿の参加者の記事も書かれたのでぜひご覧ください。

僕と開発合宿

最初の、はてなブックマークの開発合宿にも参加し、その後もほとんどの開発合宿に大なり小なり関わってきました。

最近でこそマネジメントっぽいことをしていますが、僕はもともとは長い間エンジニアをやってきました。長くやっていたため、どちらかというとレガシーなサービスを任されることが多く、開発合宿は普段できないような開発をする絶好の機会となっていました。

そのため開発合宿では異常にテンションが上がり、夜中までコードを書きまくるという体験を心から楽しんできました(夜中まで書かなきゃいけないってことは全然無く、寝る人は寝てます)。

その後、ディレクター、プロデューサー、今の開発本部長、とやれることは増えていったのですが、「合宿好き」の血は体に刻まれてしまい、今はもっぱら合宿を企画する、という形で合宿に参加しています。

今は業務でコードを書く事はほとんど無いのでそういう意味でも合宿は自分にとって貴重な機会になってきました。

今年の合宿も(なんと)明日から始まります。去年は約40人参加でしたが、今年は約50人の参加を予定しています。無事合宿が成功し、来年も実施できるようにがんばります!参加者の人も楽しんで、目的意識をしっかりもって取り組んでください!!

というわけで、なんか真面目な感じになってしまいましたが、次は新入社員の id:stefafafan です!楽しいエントリ期待!

お菓子工場の夢

久しぶりに夢日記を書く。


お菓子を作る工場を見学している。巨大な機械の中を縫うようにベルトコンベアが走り、その上を低い円柱状のお菓子が流れていく。
行程が進み、成形され、ミントブルーにコーティングされたお菓子たちは、あるものはさざ波のような、またあるものはお城のような、不思議に動きをもっている。
やがてパッケージにつめられたその箱には「12のうごき、12のあじ」と書かれていた。
色は一色なのに動きと味にバリエーションがあるのが新しい!と思って目が覚めた。

ブログを始めたきっかけ

今週のお題「私がブログを始めたきっかけ」に参加します。
もともとはgeocitiesでウェブ日記を書いていた。HTML手書きで友達だけが見てるような。という話は以前「僕のオープンインターネット - 大西ブログ」で書いた。

その後、はてなに入って人力検索サイトを運営していたわけだけど、そのサイトの中に「スタッフ日記」というコーナーを作った。簡単な日記を書ける仕組み。入社して独力でやった初めての新規の機能だった気がする。diary.cgi。.cgi かよって感じだけど当時は社内にフレームワークもなく、Apache + CGI で動かしていた。その後 mod_perl (もちろん1) 導入して、cgiApache::Registry で動かすようにして(use strictを学んだ)、その後フレームワークが作られた。

話が逸れた。

2001年8月から開始したスタッフ日記コーナーは当時のスタッフ3人で更新していた。その後2003年にはてなダイアリーというサービスを作って、スタッフ日記はそれぞれの日記にインポートした。
これが最初のエントリ。今読むと緊張感がある。はてなの使い方提案 - 大西日記 - はてなダイアリー
はてなに入社して最初の仕事が日記の仕組みを作ることで、その後何年にもわたって日記(ブログ)システムをエンジニアとして運用して、その後はてなブログというサービスをディレクターという立場で作ることになるのであった。
ブログサービスを始めたきっかけでした。こちらからは以上です。

仰げば尊し!田んぼの学校 恵み編に参加してきました

宝酒造さんが主催している「田んぼの学校」!最終回である第4回、「恵み編」のレポートです。5月から始まった田んぼの学校も7ヶ月を経てついに卒業式です。


(この記事は、宝酒造提供によるはてなPR企画の一環です。後日DigiStyle京都で参加レポートがまとめられる予定です。)

田んぼの学校とは

宝酒造「田んぼの学校」では、お米(もち米)づくりを体験しながら田んぼ周辺の生物を観察するほか、お米から本みりんができるまでの流れも学習します。これら体験を通して、自然の恵みと命のつながりを学びます。

宝酒造 田んぼの学校 | 環境活動 | 宝酒造株式会社
  • 第1回: 米づくり/田植え編
  • 第2回: 米づくり/草取り編
  • 第3回: 米づくり/収穫編
  • 第4回: 恵み編

全4回のイベントもついに最終回。自分たちの手で植え、草を取り、収穫したもち米やそれを原料にしたみりんを使って料理をしたりみりんやおせち料理について学びます。
今回もこれまで同様、 id:chris4403 さん一家と一緒に参加してきました!

始業式

12月も半ばになり、こないだ収穫したと思ったら季節はもう冬。いつもはドライブで出かける田んぼの学校ですが、最終回は「ラ・キャリエール クッキングスクール」でした。

京都市役所を見下ろせる素敵なロケーション!

結婚式場にも使えそうなスクール内のホールで最終学期の始業式です。いつも通り校長のご挨拶から始まります。

1時間目 みりんの楽校(がっこう)

1時間目の授業は大人と子どもに分かれて受けます。大人は「みりんの楽校(がっこう)」。みりんや清酒の料理に及ぼすちからを学びます。

みりんが出来るまで。みりんがどうやってできるのか考えたことも無かった…。

そして、「本みりん」と「みりん風調味料」は全然違うものだった!

  • 本みりん
    • アルコール分が含まれているので酒税がかかる
    • 複雑な糖類による味、アルコールによる生臭みを消す効果や味のしみこみ、煮崩れ防止などの効果がある
  • みりん風調味料
    • アルコールを入れずに作るので酒税がかからない
    • アルコールや糖類の効果が無い

全然違う!びっくりしました。

というわけで利きみりん。「本みりん」と「みりん風調味料」を比べてみましょう、というコーナーですが…
これが、匂いを嗅ぐだけで全然違うものでした。甘い中にも清酒のようなよい香りのする本みりんに比べて、人工的な甘い匂いと酸っぱい匂いが混じったみりん風調味料。

そして、調理したものを食べ比べても差は歴然でした。本みりんで作った方が

  • 歯触りが全然違う。本みりんでは柔らかく、みりん風の方は堅さが残っている
  • 甘さがまろやかで不自然さがない。みりん風の方はべたっとした甘さ
  • 良くしみこんでいる。噛むと中から汁がほとばしるような感じ

右が「本みりん」だったのですが、食べた後も差は歴然。しっかりと汁が吸い込まれているのがわかります。

本みりんのすごさは宝酒造さんのサイトにも詳しく載っていました。
タカラ本みりん | 調味料 | 商品紹介 | 宝酒造株式会社

そして、みりんだけでなく、「清酒」と「料理酒」にも違いがあるんですね。料理酒も、みりん風調味料と同様に酒税を免除するために塩分を入れて不可飲処理をしているそうです。なるほどー、そりゃ本みりんや清酒の方が美味しいわなーと納得。
http://www.takarashuzo.co.jp/cooking/tsubo/index02.html

と、親たちがアルコールを摂取しながら本みりんについて学んでいる間に、子どもたちは田んぼで作ったもち米から作ってもらえる「本みりん」のラベルを手描きで作っていました。どんなラベルにしたの?って聞いても「絶対内緒」と教えてくれません。本みりんが届くのが楽しみです。

2時間目 料理教室

2時間目はメインイベント、「料理教室」です。まずは講師の先生の見本を見ながら全体の指導を受けます。

今日一日でこんなに作ります!

こんなテレビの料理番組みたいなセットで手元を拡大してもらいながら詳しく説明してくれます。下の子は「これテレビでやるの?」って勘違いしてました。

説明を熱心に聞いてる下の子。

聞きながらだんだん変なポーズをし始める下の子。

ひとしきりの説明を受けて、用意してもらったエプロンに着替えて張り切る子どもたちです。

3つの教室に分かれて、家族ごとに一つのアイランドキッチンを借りて(贅沢!)調理開始です。

白みそのお雑煮

一品目は白みそのお雑煮。本当は複数の料理を段取りよく作ったのですが、時系列だと混乱するので料理ごとにまとめてみました。

まずはお雑煮の具になる人参と大根を短冊切り。左手は猫の手!子供用包丁は使ったことあったのですが大人用の包丁でおっかなびっくり、でも上手に切れました。

京風に白みそ仕立てです!白みそは大量に入れるので鍋に入れる前に溶いておきます。

椀の底に茹でたお餅を入れて、白みそ汁を入れて仕上げは三つ葉。センスの見せ所ですね。(煮てる時の写真撮り忘れた)

お雑煮できあがり!

若鶏のきじ焼き

鶏もも肉を下ごしらえ。余分な脂身や皮を切り落として軟骨を取り除きます。

塩こしょうで下味をつけます。「高いところから塩をふると満遍なくふれます」と教えられるも、背の低い下の子はこれが限界。

フライパンで焼きます!

いい色!美味しそうに焼けました。この後オーブンでさらに焼きます。

醤油、みりん、お酒を大さじ2杯ずつ、味付けの準備をしておきます。慎重に計量しています。

オーブン調理後は、先ほどつくった調味料を絡めてさらに焼きます。

焼けたら、少し冷まして食べやすい大きさに切って、

盛りつける!焼き汁を上からかけるとそれっぽい。

若鶏のきじ焼き、できました!つけ合わせはししとう!

大豆入りのごまめ

三品目は「ごまめ」。田作(たづくり)とも言いますね。おせち料理の定番です。炒り大豆も入ります。

ごまめを炒めて水分を飛ばした後、

調味料を粘り気が出るまで煮詰めて、炒り大豆と合わせます。

炒め上がったら、バットに並べて熱を冷まして、

皿に取り分けます。

出来上がり!簡単なのにこの照りはみりんの効果か!みりん万歳!

出し巻き

四品目は出し巻き玉子!これ上手に巻けたらプロっぽいやつ!

卵割る下の子。卵を割るのに異常な執着を見せて、料理始まった瞬間から「卵先に割っとく?僕割るけど?」って言い続けたけどようやく割れました。上手に割れて良かった。

だし汁と混ぜた卵を四角いフライパンで焼く!そして巻く!お姉ちゃんはさすがに上手。一人で上手に巻けました。

下の子は僕と一緒に。いい焼き色がついて美味しそう。こちらも上手にできました。

巻き簀に巻いて冷ましたあと、切り分けます。

下の子も。

出し巻き、出来ました!斜めに切ったのは上の子のセンスです。

みたらし風だんご

最後にデザート。みたらし風団子。白玉粉から団子を作るところまではあらかじめできていました。

フライパンで白玉団子を焼く。くっつくやすいから注意してください、と言われたけど確かにくっつくくっつく。細心の注意をはらって焼いてます。

上の子とバトンタッチして、たれと絡めます。

またバトンタッチ。たれとよく絡んだら、つぎは配膳。

上手にできました!照りっ照り。これもみりんの力か。


というわけで…

全部の料理が完成しましたーー。なにこれオシャレじゃないですかー。

「いただきます」と言うやいなや、料理にかぶりつく子どもたち。自分で作った料理は格別ですね。結構ボリュームあったのに残さず完食しました!
「ごまめ上手にできたから、おばあちゃんの家でも作ろうよ」とか会話も弾みます。

3時間目 お正月をもっと楽しもう!

満腹満足で迎える3時間目は、「お正月をもっと楽しもう!」と題して、おせち料理について学びます。

おせち料理に込められた意味、はいはい知ってます!と思ったら・・・

出たーーーー!!!お節かるた!!!!「込められた意味」を上の句よろしく詠んで、対応する絵札を取るという斬新なかるたです!
うちの子のテーブルは異常に盛り上がり、これだという絵札にテーブルの子どもたちが同時に手を伸ばし「ちはやふる」もかくやという熱戦が繰り広げられました。同着の全員がお手つきというシーンも何度も…。

卒業式・終わって

楽しかった「田んぼの学校」も全ての授業が終わって、卒業式です。えっもう?という気分でいっぱいです。

chris4403一家の背中越しに卒業証書授与。本物の学校の卒業式よろしく、一家族ずつ名前が呼ばれ、校長先生から卒業証書を手渡しされます。

もう人生で手にする事も無いと思っていた卒業証書。

おみやげには、スパークリング清酒「澪」、できたばっかりのお餅!そして3時間目の授業でも出てきた「節句かるた」!
お餅はしゃぶしゃぶ用の薄いのと太いのと二種類いただいたので、早速その日の夜は鍋にして薄い方のお餅をいただきました!肉より餅が人気の鍋になりました!
節句かるたは、正月に実家に帰ったらおせち料理と一緒に両親と子どもと遊ぼうと楽しみにしています。

いただいたものはそれだけでなく、調理実習で使った「タカラ本みりん」「料理のための清酒」のエプロンとバンダナを家族4人分いただいて帰りました!企業グッズ好きの我が家にはこれも嬉しいプレゼント。今度家族で料理するときは全員でまたこれを着たいです。

おまけ

テレビ取材が入っていたので、その日の夕方のKBSのニュースをチェックしたら、うちの子がアップで映ってました。ちょっと嬉しい。

まとめ

というわけで、7ヶ月間全4回の田んぼの学校が無事に終わりました。農作業体験を行える、という気軽な気持ちで参加したのですが、単に農作業を行うだけでなく、里山の自然に触れ、生き物に触れ、その生き物が田んぼを育むという事を全身で実感しました。
また、そこから米がぐんぐん成長したのを自分の目で見届け、それがさらにみりんやお酒になり、調理に使われることで食べ物の魅力を何倍にも引き出す、という壮大な手間の果てに美味しいご飯を食べれるということを学びました。
家族で一緒に汗を流して作業する楽しさに加え、沢山の発見と学びを与えてくれた「田んぼの学校」、そしてそれを運営されている宝酒造さんに感謝して、この4回のレポートを締めくくろうと思います。ありがとうございました!!

「田んぼの学校」過去の記事

[第1回: 米づくり/田植え編]
田んぼの学校で田植え体験してきました - 大西ブログ
[第2回: 米づくり/草取り編]
今度は草とりだ!田んぼの学校第2回に参加してきました - 大西ブログ
[第3回: 米づくり/収穫編]
生命賛歌!田んぼの学校収穫編に参加してきました - 大西ブログ
はてなで一緒に働きませんか?