研究用のデータセットに大量のbeneign softwareが必要になったので、Vectorから一気に落とそうと思った。

というわけでググってみたところ、数年前まではanonymous ftpがあったらしいのだが、今は使えないようなので、スクレイピングしてみることにした。


このアドバイスをもとにれっつ☆スクレイピング in Perlです
(成果物はhttps://github.com/t-chov/vectorScraperに置いてあります) 
※WWW::MechanizeとWeb::Scraperを要求します

まずは最初のコード。超ダサい
#/usr/bin/perl

use utf8;
use WWW::Mechanize;
use Web::Scraper;
use Encode;
use URI;
use YAML;

binmode(STDOUT, ':encoding(utf8)');

# Mechanizeを設定
$mech = WWW::Mechanize->new(autocheck => 1);
$mech->agent_alias('Mac Safari');

# windows NT用のソフトウェア一覧を開く
$returnMainURI = 'http://www.vector.co.jp/vpack/filearea/winnt/';
$mech->get($returnMainURI);

# 大カテゴリ
@bigCategory = ("文書作成", "インターネット&通信", "ユーティリティ",
						 "画像&サウンド", "ビジネス", "パーソナル", "家庭&趣味",
						 "学習&教育", "ゲーム", "アミューズメント", "プログラミング",
						 "ハードウェア");

for($count = 0; $counrt < @bigCategory; $count++){
	system("mkdir ./category$count");
	# メインカテゴリのページを開く
	$mech->follow_link(text => $bigCategory[$count]);
	# サブカテゴリの設定
	$scraper = scraper {
			process 'h3 a', 'url[]' => '@href';
			result 'url';
	};
	$res = $scraper->scrape($mech->content);

	foreach $category(@{$res}){
		if($category =~ /font\/$/){
			next;
		}
		print "$category\n";
		# サブカテゴリのページに遷移
		$categoryURI = "http://www.vector.co.jp/".$category;
		$mech->get($categoryURI);
		# ファイル一覧を獲得
		@fileAddr = $mech->content =~ /\/soft\/winnt\/[a-z]+\/se[0-9]{6}\.html/g;
		foreach $downloadURI(@fileAddr){
			# ファイル名を設定
			@tmp = split(/\//, $downloadURI);
			@tmp = split(/\./, $tmp[4]);
			$downFileName = $tmp[0];
			# ダウンロード
			$mech->follow_link(url => $downloadURI);
			$mech->follow_link(text => "ダウンロード");
			if($mech->content =~ /\/download\/file\/winnt/){
				$mech->follow_link(url_regex => qr/\/download\/file\/winnt/);
				$mech->get($mech->uri());
				$mech->follow_link("text"=> "こちらをクリックしてください");
				# ファイルを保存
				$directory = "category".$count."/".$downFileName;
				print "\t$downFileName\n";
				open OUTFILE,'>', $directory or die 'ERROR';
				binmode OUTFILE;
				print OUTFILE $mech->content;
				close OUTFILE;
			}
			# 元のサブカテゴリURLに戻る
			$mech->get($categoryURI);
		}
		$mech->get($returnMainURI);
	}
}
print "\n";

use Strictしてない時点で論外なのだが、当然メモリ食い尽くして落ちる。

一番苦労したのがファイルの保存で、ページを踏むと自動で落ちてくるタイプのページな上に直接リンクを叩くとリファラで弾かれるため$mech->get($url, ":content_file"=>$filename)が使えない。

follow_linkには:content_fileがないから……とここで詰まる。

結局、「ダウンロードが始まらない時はこちら」を踏むと$mech->contentにファイルのバイナリが格納されるので、これをバイナリモードで書き込むことに。

ここが一番メモリを食うので、$mechをきちんと解放してあげればいいだろう、ということで書いたのが完成版。こいつはgithubにあるので、使いたい人はどうぞ。

ちなみにautocheckを外しているのだけど、これはautocheck入れると死んでるページでエラー吐いて落ちるから。むしろ死んでるページを生かしてるVectorさんサイドに問題があると思うのだけどw