URLを入れたらWebページのタイトルを返すPerlスクリプト

掲題のツールを作りました。それも2種類。

DEMO-1

一つめはシンプルに、コマンドラインでURLを入れるとMarkdown形式で「タイトル+URL」を返すというもの。

f:id:note103:20160421010823g:plain

上のDEMOでは、

http://tdoc.info/blog/2016/04/18/ansible_up_and_running.html

というURLを入れたら、

[書評: 初めてのAnsible — そこはかとなく書くよん。](http://tdoc.info/blog/2016/04/18/ansible_up_and_running.html)

という結果が返りました。

DEMO-2

二つめは、それに比べるとちょっと複雑で、下方のDEMOを見てもちょっとわかりづらいのですが、とはいえ本来欲しかったのはこっちの方で。

これは、タイトルのわからない一つ以上のURLを含むテキストを渡すと、そのURLの部分をMarkdown形式の「タイトル+URL」に置き換えてくれるというもの。

以下のDEMOでは、ソースファイル(ur.pl)下部の__DATA__領域に、例としてこんなテキストを入れてみて、

- Perl: http://blog.geekuni.com/2016/04/interview-perls-pumpking-ricardo-signes.html; http://perl-users.jp/articles/advent-calendar/2009/casual/10.html, http://naoya.dyndns.org/~naoya/mt/archives/000657.html
- Ruby: http://itpro.nikkeibp.co.jp/article/COLUMN/20090210/324516/; http://itpro.nikkeibp.co.jp/article/COLUMN/20070621/275509/

実行したら以下の結果が返ってきた、というもの。

- Perl: [The Geek Refectory - Food for Thought: Interview - Perl’s Pumpking Ricardo Signes](http://blog.geekuni.com/2016/04/interview-perls-pumpking-ricardo-signes.html); [Encodeでラクラク日本語処理 - JPerl Advent Calendar 2009](http://perl-users.jp/articles/advent-calendar/2009/casual/10.html), [お薦めの Perl 本をいくつか紹介 : NDO::Weblog](http://naoya.dyndns.org/~naoya/mt/archives/000657.html)
- Ruby: [記者のつぶやき - 3冊のRuby書籍を通して見る、本はプログラム、もしくは旅:ITpro](http://itpro.nikkeibp.co.jp/article/COLUMN/20090210/324516/); [特別対談 - まつもとゆきひろ×結城浩、Rubyを語る:ITpro](http://itpro.nikkeibp.co.jp/article/COLUMN/20070621/275509/)

f:id:note103:20160421011216g:plain

ひとつ前のシンプル版(DEMO-1)と違うのは、複数行を渡しても返ってくること。そして、その1行あたりにまた複数のURLが入ってても、それら全部に対して変換を行う、ということ。

ぼくは結構、そういうふうに1行内に複数のURLを連ねてメモしたり、そういう行をこれというコメントも付さないままひたすら並べていく、みたいな、後から見たら何を保存したかったのかまったくわからないような記録をしてしまったりするので、そういう状況下で使うことを想定して作成&実際すでに何度か使いました。

おかげで、積年の「これ……なんのリンクだっけ?わざわざブラウザ開くのも面倒だな……」みたいなストレスが解消!よかった!
(そもそものメモの仕方を何とかしろ、という気もしますが)

ソースコード

そんな今回のコードは以下にアップしました。

GitHub - note103/urls

上記のDEMO-1は ui.pl、次のDEMO-2では ur.pl を実行しています。

ちなみに、レポジトリ上の大半のファイルはminillaで生成したデフォルトのままで、現時点で実際に自分で書いたのは

lib/Urls.pm
ui.pl
ur.pl

ぐらい。
しかもそのうち、.plファイルは呼び出し用にしか使っていないので、メインのコードは Urls.pmぐらいですが。

しかしその34〜60行目あたり、文字コード判定のためにfor文を回しているところがあるのですが、なかなかハマりましたね……。

for my $url (@urls) {
    my $res   = $agent->get($url);
    my $title = $res->title();

    my $content = $res->header('Content-Type');
    my @encode = qw/utf-8 cp932 euc-jp/;
    my $char;
    for my $encode (@encode) {
        $char = $1 if ($content =~ /charset=['"]?($encode)/i);
    }

    my $decoder;
    if ($char) {
        my $enc = find_encoding $char;
        $title = $enc->decode($title);
    } else {
        $decoder = Encode::Guess->guess($title);
        try {
            ref($decoder) || die "Can't guess: $decoder";
            $title = $decoder->decode($title);
        } catch {
            $title = 'No Title';
        };
    }
    $title = encode('UTF-8', $title);
    push @result, "[$title]($url)";
}

ここでは、対象のWebページで指定されている charset の値を LWP::UserAgent で拾って、値がわからなければ Encode::Guess で判定して……みたいなことをしているのですが、とにかくその文字コードまわりの沼具合、どこまでももぐりこんでいけそうな果てしない恐怖と魅惑があります……。

そこで具体的にどんな風にハマって、どういう経緯を辿って解消に至ったか、そして現時点の問題点は何か、みたいなことまで書きはじめると、さらに数日分の労力を費やしてしまいそうなので、それらについてはまた機会をあらためたいですが、じつはその過程において、今回も前回のPerlスクリプトに引き続き、
note103.hateblo.jp

Perl入学式の先輩方々、とくに校長の @papix さんと、前回に続いて @xtetsuji さんには大変貴重なアドバイスを頂きました。

しかも、今回はほとんどコードまるまるの添削みたいなことまでしてもらって、もしかすると私、Perl入学式に参加して2年半ぐらい経ちますが、そのように自分のコードを頭から終わりまで見てもらって、「ここはこうした方がいい」「ここも」「あと、それも」みたいな意見をもらったの、初めてかも?

これはもう、本当に勉強になりました。そういう指摘を受けると、「えっ、そういう風にするとどこがどう良くなるんだ……?」ということを考えるきっかけになって、それまで考えたこともなかった視点から、コードやそもそもの目的などまで考え直すことができるので、非常に新鮮な体験というか。

自分は普段まったく一人であーでもないこーでもない、と書いているので、なるほど、コードレビューってこんな感じかあ〜、とその一端に触れた思いです。多謝!

おまけ

ちなみに、上記コードとは別件で、その @xtetsuji さんとの雑談で、Perlのv5.24以降の機能などについてまたいろいろ教えてもらっていたのですが、その流れで以下のような記事が公開されました。
qiita.com

これまたムチャクチャ勉強になる!
3日ぐらいに分けて読んでも全然充実しそうな濃厚記事、かつ解説じたいは平明で、初心者から中〜上級者まで楽しめる内容ではないでしょうか。

告知

さてそして、そんな(?)Perl入学式の東京編、前回のPerl記事でも紹介しましたが、来月14日に行われます。
perl-entrance-tokyo.doorkeeper.jp

今年度から東京編にかぎっては「毎月第2土曜」ということで、ペースが確定しているので、受講者さんも予定が立てやすくなったのではないでしょうか。(サポーターもだけど)
あいにく、ぼくはこの回には参加できないと思うのですが、ご都合のよろしい方はぜひどうぞ。

そしてさらに、ついにPerl入学式 in沖縄の第1回開催日が決まりました。6/18(土)!
perl-entrance-okinawa.doorkeeper.jp

沖縄!しかもすでに6名の方が参加予定のようですね。いろいろすごい!
東京から駆けつけるサポーターさんもいるようですので、皆さんぜひふるってご参加&楽しんでほしいです。