ablog

不器用で落着きのない技術者のメモ

WWW::Mechanize::AutoPager + Web::Scraper で HTML からテキストを抽出して CSV を作成してみた

やりたいこと

  • Webアプリにログインする。
  • 検索ページに移動する。
  • 検索ボタンを押下する。
  • 検索結果一覧から詳細ページに移動、テキストを抽出してCSVファイルに書込む。
  • 次のページに移動して、同じことを繰り返す。
  • 次のページがなくなったら終了する。

ソースコード

  • foo_scraper.pl
#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Mechanize;
use WWW::Mechanize::AutoPager;
use Web::Scraper;
use Text::CSV;
use utf8;
use Encode;

my $list_scraper = scraper { process '/html/body/div/div[3]/table/tbody/tr/td[3]/a', 'link[]' => '@href'; };
my $detail_scraper = scraper {
	process '/html/body/div/div/form/fieldset/div[1]/span', '1' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[2]/span', '2' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[3]/span', '3' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[4]/span', '4' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[5]/span', '5' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[6]/span', '6' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[7]/span', '7' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[8]/span', '8' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[9]/span', '9' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[10]/span', '10' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[11]/span', '11' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[12]/span', '12' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[13]/span', '13' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[14]/span', '14' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[15]/span', '15' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[16]/span', '16' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[17]/span', '17' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[18]/span', '18' => 'TEXT';
	process '/html/body/div/div/form/fieldset/div[19]/span', '19' => 'TEXT';
};

my $mech = WWW::Mechanize->new;
my $csv = Text::CSV->new;
$mech->autopager->add_site(
	url => 'http://foo.db.ablog.co.jp/',
	nextLink => '//a[@title="Go to next page"]' );
$mech->get('http://foo.db.ablog.co.jp/foo-bar/login');
$mech->submit_form('fields', {'name', 'foo', 'password', 'foo'}); # login
$mech->get('http://foo.db.ablog.co.jp/foo-bar/contract');         # move to list page
$mech->submit_form();                                             # submit search button

my @url_list;
while(){
	my $list = $list_scraper->scrape($mech->content); # scrape list page
	push @url_list, @{$list->{link}};                 # add urls to array
	$mech->get($mech->next_link);                     # move to next page
	last if ( $@ or !defined($mech->next_link) );     # quit if last page
}

open my $out_file, ">:encoding(utf8)", "list.csv" or die $!;
foreach (@url_list) {
	$mech->get("http://foo.db.ablog.co.jp/foo-bar/$_");        # move to detail page
	my $detail = $detail_scraper->scrape($mech->content);      # scrape detail page
	$csv->combine(@{$detail}{sort {$a <=> $b} keys %$detail}); # to csv
	print $out_file $csv->string . "\n";                       # write a line to file
}
close $out_file;

__END__

60行くらいでできた。
CPANモジュールすごい! ありがとう CPAN Author の方々!