ishiducaの日記 このページをアンテナに追加 RSSフィード

2011-06-06

[][Parallel::ForkManager][Clone]Pixiv 漫画コンテンツの非同期DL 12:29 [Parallel::ForkManager][Clone]Pixiv 漫画コンテンツの非同期DL - ishiducaの日記 を含むブックマーク はてなブックマーク - [Parallel::ForkManager][Clone]Pixiv 漫画コンテンツの非同期DL - ishiducaの日記 [Parallel::ForkManager][Clone]Pixiv 漫画コンテンツの非同期DL - ishiducaの日記 のブックマークコメント

WWW::Pixiv::Downloadで漫画コンテンツをDLするには

$client->download($illust_id);

とやることで可能です。この場合、漫画を構成する画像を同期ダウンロードするため、画像数が多い場合は時間がかかります。(ちなみに、漫画コンテンツの任意のページをDLするには

$client->download($illust_id, {
    manga_pages => [ 0, 2, ... ]
});

とやれば良いです。この場合も同期ダウンロードです)

「七宮姉妹【本編】」/「はいてくりん」の漫画 は49枚のコンテンツです。(唐突に)

同期DLしてると時間がかかって仕方ない!ってなるか。時間切れ(504 Gateway Time-out)で、ハイソコマデデヨ!!ってなるかで、ヤッテラレイヨ!! ってなることは必然。

なので、僕は非同期DLすることにしました。

parallel.pl こっち(gist: 1009645)にも

#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Pixiv::Download;
use Config::Pit qw(pit_get);
use Parallel::ForkManager;
use Path::Class;
use Clone;

my $illust_id = '17373419';
my $dir_home  = "$ENV{HOME}/Desktop/test_image";

my $config = pit_get('www.pixiv.net', require => {
    pixiv_id => '', pass => '',
});
die qq(! failed: "pit_get"\n) if ! %$config;

my $client = WWW::Pixiv::Download->new(
    pixiv_id   => $config->{pixiv_id},
    pass       => $config->{pass},
    # over_write => 1,
    look       => 1,
);
my $info = $client->prepare_download($illust_id);
$info->{author}->{name} =~ s:/::g;
$info->{title} =~ s:/::g;

my $dir = join '/', $dir_home, $info->{author}->{name}, $info->{title};

unless (-e $dir) {
    warn qq(! "${dir}" not found.\n);
    dir($dir)->mkpath or die qq(! failed: can not mkpath "${dir}" $!\n);
    warn qq( mkpath "${dir}" success.\n);
}

my $urls = $info->{contents}->{img_srcs};
die qq(! failed: image srcs not found.\n) unless $urls;

my $pm = Parallel::ForkManager->new(scalar @$urls);
for my $url (@$urls) {
    my $pid = $pm->start and next;
    my $clone_c = Clone::clone($client);
    $clone_c->_save_content($url, {
        path_name => $dir,
    });

    $pm->finish;
}

$pm->wait_all_children;

exit 0;
__END__

はいてくりん/七宮姉妹【本編】の漫画コンテツ 49枚 をフォークプロセスでDL

流れとしては

  • ログイン && RefererURLの取得
  • prepare_downloadメソッドの返り値から漫画コンテンツの画像のurlを配列で取得
  • 画像url分のフォークプロセスをParallel::ForkManagerで
  • $clientのクローンを作って、クローンでDLする(_save_content_メソッドはドキュメントにないけど、$client->_save_content($img_src, \%option)でピクチャーを保存します。

Parallel::ForkManager++

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20110606

2011-05-28

[][]WWW::Pixiv::Downloadでキャッシュに画像を保管する 11:52 WWW::Pixiv::Downloadでキャッシュに画像を保管する - ishiducaの日記 を含むブックマーク はてなブックマーク - WWW::Pixiv::Downloadでキャッシュに画像を保管する - ishiducaの日記 WWW::Pixiv::Downloadでキャッシュに画像を保管する - ishiducaの日記 のブックマークコメント

一時的にキャッシュする需要があるのかは別として。

memcachedBASE64エンコーディングしてキャッシュすればいいかなと

p5-www-pixiv-download/eg/cache2memcached.pl ishiduca/p5-www-pixiv-download - GitHub」に置いてあるので、勝手に弄ってください

#!/usr/bin/env perl
use strict;
use warnings;
use Cache::Memcached::Fast;
use MIME::Base64;
use Config::Pit;
use WWW::Pixiv::Download;

@ARGV or die qq(usage: $0 illust_id\n);
my $illust_id = $ARGV[0];

my $cache = Cache::Memcached::Fast->new({
    servers => [ "localhost:11211" ],
});

my $config = pit_get('www.pixiv.net', require => {
    pixiv_id => '', pass => '',
});
die qq(! failed: can not pit_get\n) if ! %$config;

my $client = WWW::Pixiv::Download->new(
    pixiv_id   => $config->{pixiv_id},
    pass       => $config->{pass},
    look       => 1,
    over_write => 1,
);


my($buf, $stuffix);
$client->download($illust_id, {
    mode => 'm',
    cb   => sub {
        my($chunk, $res, $proto) = @_;
        unless ($stuffix) {
            $stuffix = $res->header('Content-Type');
            $stuffix =~ s|image/||;
        }
        local $/;
        $buf .= $chunk;
    },
});

# memcachedに書き込み
$cache->set($illust_id,  encode_base64 $buf) or die $!;

# 書き込んだデータを読み込んで出力&memcachedから削除
test_print( $illust_id, "${illust_id}.${stuffix}");

sub test_print {
    my($illust_id, $filed_path) = @_;

    open my $fh, '>', $filed_path or die $!;
    binmode $fh;
    print $fh decode_base64 $cache->get($illust_id);
    close $fh;

    $cache->delete($illust_id);
}

もっといい方法があるはずなので、ツッコミよろしくお願いします。

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20110528

2011-05-20

[]WWW::Pixiv::Downloadを使ったサンプル その1 22:50 WWW::Pixiv::Downloadを使ったサンプル その1 - ishiducaの日記 を含むブックマーク はてなブックマーク - WWW::Pixiv::Downloadを使ったサンプル その1 - ishiducaの日記 WWW::Pixiv::Downloadを使ったサンプル その1 - ishiducaの日記 のブックマークコメント

WWW::Pixiv::Download的な物 その2」の方を使います。

コマンドラインから illust_id のコンテンツを保存するスクリプト

$ perl pixiv_dl.pl 0123456789

ってやると $HOME/Pictures/Pixiv ディレクトリ以下に「author/title/」のディレクトリを作って、その中にコンテンツを保存します

--> success: login. "http://www.pixiv.net/mypage.php" now.
--> access: "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=0123456789"
--> not found directory "/Users/YOU/Pictures/Pixiv/some_author/some_title".
--> create new directory "/Users/YOU/Pictures/Pixiv/some_author/some_title".
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_m.jpg"
--> access: "http://www.pixiv.net/member_illust.php?mode=manga&illust_id=0123456789"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p0.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p1.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p2.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p3.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p4.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p5.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p6.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p7.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p8.jpg"
--> success: download. "/Users/YOU/Pictures/Pixiv/some_author/some_title/0123456789_p9.jpg"

という感じでダウンロード状況を提示してくれる

pixiv_dl.pl

#!/usr/bin/env perl -s
use strict;
use warnings;
use Path::Class;
use Config::Pit;
use WWW::Pixiv::Download;

our($h);
my $usage = "usage: $0 illust_id\n";

$h and $usage and exit 0;
@ARGV or die $usage;

my $config = pit_get('www.pixiv.net', require => {
    pixiv_id => 'my pixiv_id',
    pass     => 'my pass',
});
die 'pit_get failed' if ! %$config;


my $client = WWW::Pixiv::Download->new(
    pixiv_id => $config->{pixiv_id},
    pass     => $config->{pass},
    look     => 1, # このオプションを付けるとDLの進捗状況を示してくれる
);

my $illust_id   = $ARGV[0];

# メタデータ(作者名とか作品タイトルとか)を取得
my $scraped_response = $client->prepare_download($illust_id);

$scraped_response->{author_name} =~ s/\//_/g;
$scraped_response->{title}       =~ s/\//_/g;
my $dir = join '/',
    "$ENV{HOME}/Pictures/Pixiv",
    $scraped_response->{author_name},
    $scraped_response->{title};

# ディレクトリを作る
unless (-e $dir) {
    warn qq(--> not found directory "${dir}".\n);
    dir($dir)->mkpath or die $!;
    warn qq(--> create new directory "${dir}".\n);
    $dir = "${dir}/";
}

$client->download($illust_id, {
    mode      => 'medium',
    path_name => $dir,
});

$client->download($illust_id, {
    path_name => $dir,
});

exit 0;

[]WWW::Pixiv::Download的な物 その2 20:50 WWW::Pixiv::Download的な物 その2 - ishiducaの日記 を含むブックマーク はてなブックマーク - WWW::Pixiv::Download的な物 その2 - ishiducaの日記 WWW::Pixiv::Download的な物 その2 - ishiducaの日記 のブックマークコメント

【補足】最新のバージョンは ishiduca/p5-www-pixiv-download - GitHub にあります。こちらは、ユーザーエージェントを WWW::Mechanize から LWP::UserAgent に変更しています(2011.05.22)

WWW::Pixiv::Download的なもの」のLWP::UserAgent版...にするついでにメソッドもいじった。

コードを書くときは WWW::Mechanize の方が楽ということを実感もした。

メソッド

  • new
my $client = WWW::Pixiv::Download->new(
    pixiv_id => 'your pixiv id',
    pass     => 'your pass',
    look     => 1, # ページ変遷を表示したいときのオプション
);
  • download
# illust_idのオジリナルサイズのファイルをダウンロードします
# マンガ形式の場合は、漫画ページで表示されるイラスト(複数枚)をダウンロードします
$client->download($illust_id);
  or
$client->download($illust_id, {
    mode      => 'medium',
    path_name => 'foo/bar/',
    file_name => $new_file_name, # 
});
  or
$client->download($illustid, {
    cb => \&callback,
});
# cbで指定するコールバックオプションは LWP::UserAgent の ":content_cb"
  • prepare_download

ダウンロードするイラスト(漫画)のタイトル、概要、作者名を含んだハッシュリファレンスを返します。(Web::Scraper、$scraper->scrape(...)の結果が入ってる )

my $contents_data = $client->prepare_download($illust_id);
my $illust_title       = $contents_data->{title};
my $illust_description = $contents_data->{description};
my $author_name        = $contents_data->{author_name};

todo

  • マンガ形式のコンテンツの処理をどうしたもんかと
  • ごちゃごちゃしてるコードをどうにかしたい

WWW/Pixiv/Download.pm

package WWW::Pixiv::Download;

use strict;
use Carp;
use URI;
use LWP::UserAgent;
use Web::Scraper;
use File::Basename;

our $VERSION = '0.0.2';

my $home   = 'http://www.pixiv.net';
my $login  = "${home}/login.php";
my $mypage = "${home}/mypage.php";

my $default_path_name = './';

sub new {
    my $class = shift;
    my %args  = @_;

    $args{is_logged_in} = '0';
    $args{Referer}      = '';
    $args{user_agent}   = LWP::UserAgent->new( cookie_jar => {} );

    push @{$args{user_agent}->requests_redirectable}, 'POST';

    bless \%args, $class;
}

sub download {
    my($self , $illust_id, $args) = @_;

    my $res_scrape = $self->{res_scrape};
    unless ($res_scrape->{img_src}        =~ m!$illust_id!
        and $res_scrape->{to_bigImg_href} =~ m!$illust_id!
        and $self->{Referer}              =~ m!$illust_id!) {
            $res_scrape = $self->prepare_download($illust_id);
    }

    if ($args->{mode} eq 'medium' or $args->{mode} eq 'm') {
        delete $self->{mode};
        $self->save_file($res_scrape->{img_src}, $args);
    } else {
        my $res = $self->{user_agent}->get("${home}/" . $res_scrape->{to_bigImg_href},
            'Referer' => $self->{Referer},
        );
        Carp::croak qq(! Download failed: ) . $res->status_line . "\n" if $res->is_error;
        $self->{Referer} = $res->base;
        warn '--> access: "' . $self->{Referer} . qq("\n) if $self->{look};

        if ($res->base =~ m!mode=big!) {
            my $scraper = scraper {
                process '//img[1]', 'img_src' => '@src';
            };
            my $res_scrape = $scraper->scrape($res->decoded_content);
            $self->save_file($res_scrape->{img_src}, $args);
        } else {
            my $content = $res->decoded_content;
            while ($content =~ m!unshift\('(http://([^\']+)?)'!g) {
                $self->save_file($1, $args);
            }
        }
    }

    $self;
}

sub prepare_download {
    my($self, $illust_id) = @_;

    Carp::croak qq(! failed: not found param "illust_id".) unless $illust_id;

    $self->login if $self->{is_logged_in} ne '1';

    my $uri = URI->new( "${home}/member_illust.php" );
    $uri->query_form(
        mode      => 'medium',
        illust_id => $illust_id,
    );

    my $res   = $self->{user_agent}->get( $uri );
    my %query = URI->new( $res->base )->query_form;

    if ($res->is_error) {
        Carp::croak '! failed: '. $res->status_line
            .': can not go to "'. $uri->as_string . qq("\n);
    } elsif ($query{mode} ne 'medium' or $query{illust_id} ne $illust_id) {
        Carp::croak '! failed: can not go to "'. $uri->as_string . '". now "'
             . $res->base . qq("\n);
    }

    $self->{Referer} = $res->base;

    warn '--> access: "'. $self->{Referer}. qq("\n) if $self->{look};

    my $scraper = scraper {
        process '//h3[1]', 'title' => 'TEXT';
        process '//p[@class="works_caption"]', 'description' => 'HTML';
        process '//a[@class="avatar_m"]', 'author_name' => '@title';
        process '//a[@class="avatar_m"]', 'author_url' => '@href';
        process '//div[@class="works_display"]/a[1]', 'to_bigImg_href' => '@href';
        process '//div[@class="works_display"]/a[1]/img[1]', 'img_src' => '@src';
    };

    $self->{res_scrape} = $scraper->scrape($res->decoded_content);
}

sub login {
    my $self = shift;
    my %args = @_;
    my $res;

    $self->{pixiv_id} = $args{pixiv_id} if $args{pixiv_id};
    $self->{pass}     = $args{pass}     if $args{pass};

    $self->{pixiv_id} or Carp::croak qq(! failed: not found "pixiv_id".\n);
    $self->{pass}     or Carp::croak qq(! failed: not found "pass".\n);

    $res = $self->{user_agent}->post($login, content => {
        'mode'     => 'login',
        'pixiv_id' => $self->{pixiv_id},
        'pass'     => $self->{pass},
    });

    if ($res->is_error) {
        $self->{is_logged_in} = '0';
        Carp::croak '! failed: login. ' . $res->status_line;
    } elsif ($res->base =~ m!index\.php!) {
        $self->{is_logged_in} = '0';
        Carp::croak qq(! failed: login. because of bad "pixiv_id" and "pass"\n);
    }
    $self->{Referer} = $res->base;
    $self->{is_logged_in} = '1';

    warn '--> success: login. "' . $self->{Referer} . '" now.'. "\n" if $self->{look};
    $self;
}

sub save_file {
    my($self, $img_src, $args) = @_;
    my $res;

    my $file_name = $args->{file_name} || basename $img_src;
    my $path_name = $args->{path_name} || $default_path_name;
    my $file_path = "${path_name}${file_name}";
    $file_path =~ s/\?.*//;
    unless (-e $file_path) {
        if (ref $args->{cb} eq 'CODE') {
          $res = $self->{user_agent}->get($img_src,
            'Referer'     => $self->{Referer},
            ':content_cb' => $args->{cb},
         );
      } else {
            $res = $self->{user_agent}->get($img_src,
                'Referer'       => $self->{Referer},
                ':content_file' => $file_path,
            );
      }
        Carp::croak '! Download failed: '. $res->status_line . "\n" if $res->is_error;
        warn '--> success: download. "' . $file_path . qq("\n) if $self->{look};
    } else {
        warn '--> skip: "'. $file_path . qq(" that already exists.\n) if $self->{look};
    }

}

1;

コマンドラインからダウンロードさせるスクリプトは明日アップします

GracelinGracelin2011/10/08 16:25Why does this have to be the ONLY reliable socure? Oh well, gj!

dctkfydctkfy2011/10/10 19:11kkQ9yQ , [url=http://ghqjxhukgnhw.com/]ghqjxhukgnhw[/url], [link=http://lstbpwczbflg.com/]lstbpwczbflg[/link], http://vnilkrgwluob.com/

riemxpriemxp2011/10/12 00:03jLmV3P <a href="http://sdavwdzlkusk.com/">sdavwdzlkusk</a>

qqmmqrgnssqqmmqrgnss2011/10/13 01:46x3v1n6 , [url=http://vkilptnlqxpd.com/]vkilptnlqxpd[/url], [link=http://qhisbkxjuzpg.com/]qhisbkxjuzpg[/link], http://cgqzyaxvzjwz.com/

bfnhpqpeubbfnhpqpeub2014/04/11 15:18bimtqqfsm, <a href="http://www.zbcxpykjkw.com/">elbrdiaper</a> , [url=http://www.lqbypjbpic.com/]axxhfzpxtr[/url], http://www.sgwymcxhuo.com/ elbrdiaper

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20110520

2011-05-18

[]WWW::Pixiv::Download的なもの 17:12 WWW::Pixiv::Download的なもの - ishiducaの日記 を含むブックマーク はてなブックマーク - WWW::Pixiv::Download的なもの - ishiducaの日記 WWW::Pixiv::Download的なもの - ishiducaの日記 のブックマークコメント

【補足】最新のバージョンは ishiduca/p5-www-pixiv-download - GitHub にあります。こちらは、ユーザーエージェントを WWW::Mechanize から LWP::UserAgent に変更しています(2011.05.22)

WWW::Pixiv::Download があればいいんだけど見当たらないので、それっぽいの書いてみた。

残っているTODOも多いんだけど、全部こなすと時間かかりそうなので、めどが付いたところで晒してみますね。

出来ること

  • イラストコンテンツの Mサイズのダウンロード
  • イラストコンテンツの オリジナルサイズのダウンロード
  • 漫画コンテンツの Mサイズのダウンロード

SYNOPSIS

use WWW::Pixiv::Download;

my $client= WWW::Pixiv::Download->new(
    pixiv_id => 'your pixiv id',
    pass     => 'your pixiv password',
);

my $illust_id = 'xxxx123';

$client->download($illust_id);
  • 上記の例だと、illust_id "xxxx123" のオリジナルサイズのイラストをダウンロードできます。
  • ただし、このコンテンツが漫画の場合は、漫画を構成する(複数の)イラストをダウンロードすることになります。
  • コンテンツのMサイズのイラストをダウンロードする場合はオプションをつけます
$client->download($illust_id, {
    mode => 'medium',
});
  • ファイル名を変更して保存する場合は
$client->download($illust_id, {
    file_path => 'foo/bar/file.name',
});

実際にコマンドラインから illust_id を指定してコンテンツをDLするスクリプト(pixiv_dl.pl)

#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Pixiv::Download;
use Config::Pit;

@ARGV or die qq(usage: $0 illst_id);

my $illust_id = $ARGV[0];
my $config = pit_get('www.pixiv.net', require => {
    pixiv_id => 'pixiv_id',
    pass     => 'pass',
});
die 'pit_get failed.' if ! %$config;

my $client = WWW::Pixiv::Download->new(
    pixiv_id => $config->{pixiv_id},
    pass     => $config->{pass},
);

$client
    ->download($illust_id, { mode => 'medium' })
    ->download($illust_id)
    ;

exit 0;
$ perl pixiv_dl.pl 12345

みたいな感じで

WWW/Pixiv/Download.pm

package WWW::Pixiv::Download;

use strict;
use Carp;
use URI;
use WWW::Mechanize;
use Web::Scraper;
use File::Basename;

my $home   = 'http://www.pixiv.net';
my $login  = "${home}/";
my $mypage = "${home}/mypage.php";

sub new {
    my $class = shift;
    my %args  = @_;

    $args{pixiv_id} or Carp::croak qq(not found "pixiv_id");
    $args{pass}     or Carp::croak qq(not found "pass");

    $args{user_agent} = WWW::Mechanize->new( autocheck => 1)
        unless exists $args{user_agent};
    bless \%args, $class;
}

sub download {
    my $self      = shift;
    my $illust_id = shift;
    my $args      = shift || {};
    my($mode, $file_path) = ($args->{mode}, $args->{file_path});
    $self->{illust_id} = $illust_id;

    die qq(not found param "illust_id".) unless $illust_id;

    if ($self->login &&  $self->check_mode_eq_medium) {
        my $scraper = scraper {
            process '//div[@class="works_display"]/a[1]', 'to_bigImg_href' => '@href';
            process '//div[@class="works_display"]/a[1]/img[1]', 'img_src' => '@src';
        };

        my $res = $scraper->scrape($self->{user_agent}->content);

        if ($mode eq 'medium' or $mode eq 'm') {
            $self->_save_content($res->{img_src}, $file_path);
        } elsif ($res->{to_bigImg_href} =~ m|mode=big|) {
            $self->{user_agent}->get(join '/', $home, $res->{to_bigImg_href});
            $scraper = scraper {
                process '//img[1]', 'img_src' => '@src';
            };
            $res = $scraper->scrape($self->{user_agent}->content);
            $self->_save_content($res->{img_src}, $file_path);
        } else {
            $self->{user_agent}->get(join '/', $home, $res->{to_bigImg_href});
            my $content = $self->{user_agent}->content;
            while ($content =~ m|unshift\('(http://([^\']+)?)'|g) {
                $self->_save_content($1, $file_path);
            }
        }
    }

    $self;
}

sub _save_content {
    my $self = shift;
    my $url  = shift;
    my $file_path = shift;

    $self->{user_agent}->get($url);
    $file_path ||= basename $self->{user_agent}->uri->as_string;
    $self->{user_agent}->save_content(re_file_name( $file_path));
}

sub check_mode_eq_medium {
    my $self  = shift;
    my $uri   = $self->{user_agent}->uri;
    my %query = $uri->query_form;
    unless ($query{mode} eq 'medium' and $query{illust_id} eq $self->{illust_id}) {
        $self->to_mode_eq_medium;
        $self->check_mode_eq_medium;
    }
    return 1;
}

sub to_mode_eq_medium {
    my $self = shift;
    my $uri  = URI->new(join '/', $home, 'member_illust.php');
    $uri->query_form(
        mode      => 'medium',
        illust_id => $self->{illust_id},
    );
    $self->{user_agent}->get( $uri );
}

sub login {
    my $self = shift;
    my %args = @_;

    if ($self->{logged_in} ne '1') {
        $self->{user_agent}->get( $login );
        $self->{user_agent}->submit_form(
            form_name => 'loginForm',
            fields    => {
                mode     => 'login',
                pixiv_id => $self->{pixiv_id},
                pass     => $self->{pass},
            },
        );

        die qq(login failed $!) unless $self->{user_agent}->res->is_success;
        my $uri = $self->{user_agent}->uri->as_string;
        die qq(login failed. "$uri" now.) unless $uri eq $mypage;

        $self->{logged_in} = '1';
    }
    return 1;
}

sub re_file_name {
    my $file_path = shift;
    if (-e $file_path) {
        my ($file_name, $path, $suffix) = fileparse($file_path);
        my ($name, @exts) = split /\./, $file_name;
        my $timestmp = time;
        $file_path = re_file_name(join '', $path, (join '.', $name, $timestmp, @exts));
    }
    $file_path;
}

1;

todo

  • 漫画コンテンツのオリジナル画像のDLに対応させる
  • エラー処理が不十分
  • UserAgentをLWP::UserAgentに返る
  • メタデータ(イラストのタイトル、作者名、etc,)を扱えるようにする
  • 進捗状況を扱えるようにする
  • コールバック関数を使えるように
  • 漫画コンテンツの画像へのURLを正規表現以外の方法で取得する

SerenaSerena2014/05/07 03:36That's the thikinng of a creative mind

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20110518

2011-02-19

[]カリー化 その2 21:58 カリー化 その2 - ishiducaの日記 を含むブックマーク はてなブックマーク - カリー化 その2 - ishiducaの日記 カリー化 その2 - ishiducaの日記 のブックマークコメント

昨日(カリー化 - ishiducaの日記)」の続き。

カリー化する関数を作ってみる(curry)

use strict;
use warnings;

# カリー化する関数
sub curry {
    my $func = shift;
    my @arg  = @_;
    sub { $func->(@arg, @_); };
}
# 合計する関数
sub sum {
    my $s;
    $s += $_ for @_;
    $s;
}

my $sum   = \&sum;

print $sum->(1, 2, 3);                     # 6
print curry($sum, 1)->(2, 3);              # 6

my $curry = \&curry;

print $curry->($sum, 1)->(2, 3);           # 6
print $curry->($curry->($sum, 1), 2)->(3); # 6

これでいいのかな?

というか、これだと嬉しくない...orz

YgorYgor2014/05/06 23:47Thanks for your thtshgou. It's helped me a lot.

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20110219