work.log

元エンジニアの備忘録的ブログ

Coro::Channelを使ってクローラちっくなものを書いてみる

投稿:2014-04-04 18:10  更新:

Coro のメモ書き。

ボチボチ使い方をわかってきたつもりになってきたので、下記を参考にクローラの部品を書いてみたいと思います。

理解力がアレなのであれこれを一度にやるとハマるのでまずは下記の機能から。

  • URL を取得するスレッドを作る
  • 取得したタイトルを表示するスレッドを作る

コードはこれ。URL リストは RSS から作る。

#!/usr/bin/perl

use strict;
use warnings;
use Coro;
use Coro::LWP;
use LWP::UserAgent;
use XML::FeedPP;

    my $queue = {};
    my @url = ();

    my @feed = (
           'http://example.jp/feed',
           'http://example.com/feed',
       );

    foreach my $url (@feed) {

        my $lwp = LWP::UserAgent->new();
        my $res = $lwp->get($url);
        my $feed = XML::FeedPP->new($res->content);

        foreach ($feed->get_item()) {
            push(@url, $_->link());

        }

    }

    # コンテンツを取得するスレッドは 100
    # コンテンツを表示するスレッドは 1
    create_worker( fetcher => \&fetcher, 100 );
    create_worker( receiver => \&receiver, 1 );

    # fetcher に URL を送りつける
    queue("fetch")->put($_) for @url;
    schedule;

# スレッドを作るサブルーチン
sub create_worker {

    my ($name, $code, $num) = @_;

    for (0 .. $num) {

        my $desc = $name . "_" . $_;

        async {
            while( 1 ){
                $code->();
            }
        };
    }

}

# スレッド間のやりとりは Coro::Channel を使う
sub queue {
    my $name = shift;
    $queue->{$name} ||= Coro::Channel->new;
}

# コンテンツを取得するサブルーチン
sub fetcher  {

    my $url = queue("fetch")->get;
    my $lwp = '';
    my $res = 0;

    $lwp = LWP::UserAgent->new();
    $res = $lwp->get($url);

    queue("receiver")->put($res->title);

}

# コンテンツを表示するサブルーチン
sub receiver  {

    my $receive = queue("receiver")->get;
    print "$receive\n";

}

このまでは fetcher も receiver も終了せずに待機しっぱなしになりますが、理解を深める上でこんな感じにしてみました。

ロックを全くかけていないので注意。

もうちょっと勉強してまた続きを書きたいと思います。