こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

-広告-

解決済みの質問

Perl 速度について

あるサイトの情報を取得するのに
ソースを組んで、なんとかできたのですが、

時間がかかってる気がします。
ページ数 約300ページくらい読み込んでいて
その中でも、
250ページほど、正規表現で、一部抜粋し、保存させているのですが、
ここが遅いです。
保存した容量は、
1個につき2kb~20kb
平均8kbほど

下記のような、ソースの箇所が明らかに遅い気がします。
my @words;
while ($content =~ m#<td.*?>(.+?)</td>#gs) {
my $word = $1;
$word =~ s/<.+?>//g;
$word =~ s/(\r|\n)+/\,/g;
$word =~ s/,+//g;

for( my $year=2010; $year<2017; $year++ ){
$word =~ s/$year\//\n$year\//g;
}

from_to($word,"euc-jp","utf8");
utf8::decode($word);
push(@words, $word) if $word;
}
@Word = join(',', @words) . "\n";

print @Word;
open(FILE, ">","$DATA[$i].txt") or die("error :$!");
flock(FILE, 2);
print FILE @Word;
close FILE;

内容が多いからでしょうか?
だいたい10分近くかかっております。
パソコンもcore i3と古い
Windows7を使用しています。

そんなものでしょうか?
もしくは、速くする方法はありますか?

投稿日時 - 2017-10-12 16:21:00

QNo.9385047

困ってます

質問者が選んだベストアンサー

やっぱり、LWP を使って http 通信を行っているのですね。
おそらくはhttp通信の応答時間が10分という時間がかかる原因でしょう。

私も以前(15年ほど前)に、ほぼ同じような仕組みを作ったことがあります。
そのときは LWP::UserAgent ではなく、get だけでよかったので LWP::Simpleを使いました。
確か30ページ程度を取得し、得られた内容から任意の値をファイルに書き込むスクリプトだったのですが、15秒~20秒程度で完走したように記憶しています。
[注意] 対象サーバによっては、getだけの用途でもLWP::Simpleが使えない場合があります。

get だけで良い and 対象サーバが応答してくれれば、 LWP::Simple を使うのも手と思います。

さらに、最近では Furl というモジュールもあるようです。
http://search.cpan.org/~tokuhirom/Furl-3.13/lib/Furl.pm
私は使ったことがありませんが、LWP との比較で2.5倍程度高速らしいです。(ローカルでの検証)

投稿日時 - 2017-10-13 20:25:50

お礼

お返事が遅くなり申し訳ないです。

色々試してみておりました。

Simpleは、実行できませんでした・・・
Fullもインストールしてとの指示でインストールしたのですが、
使用できませんでした。

もう少し自分で調べてみます。
また、わからないことがあったらよろしくお願いいたします。

投稿日時 - 2017-10-17 14:59:23

ANo.3

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

-広告-
-広告-

回答(3)

ANo.2

my $words;
while($content=~m[<td.*?>(.+?)</td>]gs){

my $word = $1;
$word =~ s[<.+?>|\n|\r][]g; # 文字コードeucで\rあるの?
$word =~ s[(201[0-6])/][\n$1/]g;

$words .= "$word," if $word; # 出来るだけ関数使わない
}

$words =~ s[,$][\n];

Encode::from_to($words,'euc-jp','utf8');

投稿日時 - 2017-10-13 16:33:22

お礼

ありがとうございます。
極力関数は使わないよう、考えてみます・・・

投稿日時 - 2017-10-16 13:01:04

ANo.1

こんばんわ。
一部、何をやりたいのか良くわからない箇所もありますが、文字コードのエンコードとデコード部分を while ループの外に置くと少しは速度改善します。

@Word = join(',', @words) . "\n";
この部分ですが、join(',', @words) で得られる値は文字列ですので、次のように置き換えます。
$string = join(',', @words) . "\n";

その後で、エンコード・デコードを行えば良いです。
from_to($string,"euc-jp","utf8");
utf8::decode($string);

当然、ファイルに書き込む際は次のようになります。
print FILE $string;

ですが、ボトルネックは示されたコード以外の部分だと思いますよ。

投稿日時 - 2017-10-12 22:54:04

お礼

御回答ありがとうございます。
エンコード・デコードを外にもっていくと
少し速くなりました。


>ボトルネックは示されたコード以外の部分だと思いますよ。
一応、個々にテストを行って他の箇所は遅くはなかったのですが、
組み合わせることによって、遅くなったりするのかな・・・?
強いてあげるなら、my @words;
の上に、下記のソースがあります・・・


$num=3~5ほど
$DATA=サイト側の暗号的なもの

for( my $i=0; $i<$num; $i++ ){
our $URL = 'http://あるサイト/' . $DATA[$i] . '/';

my $proxy = new LWP::UserAgent;
$proxy->agent('your own created browser name here');
$proxy->timeout(60);
$req = HTTP::Request->new('GET' => $URL);
my $res = $proxy->request($req);
my $content = $res->content;

if($res->is_success) {

投稿日時 - 2017-10-13 09:23:17

-広告-
-広告-

あなたにオススメの質問

-広告-
-広告-