0

スクレイピングしようとしているサイトに関連して、別の問題に遭遇しました。

基本的に、ページのコンテンツから不要なもののほとんどを削除しました。ここで提供されたいくつかの助けのおかげで、必要な日付を分離することができました。非改行スペースに一致するいくつかの初期の問題にもかかわらず、そのほとんどは正常に機能しているようです。ただし、データの各行をフィールドに分割することを目的とした最終的な正規表現で問題が発生しています。各線は株価指数の価格を表します。各行のフィールドは次のとおりです。

  1. ラテン アルファベットの文字と、場合によってはカンマまたはアンパサンドからなる任意の長さの名前で、数字は含まれません。
  2. 小数点以下 2 桁の数値 (インデックスの絶対値)。
  3. 小数点以下 2 桁の数値 (値の変化)。
  4. 小数点以下 2 桁の数値の後にパーセント記号 (値の変化率) が続きます。

分割前の文字列の例を次に示します。 13% 紙・パルプ333.31-0.29-0.09% 化学品729.406.010.83%

この行を分割するために使用している正規表現は次のとおりです。

$mystr =~ s/\n(.*?)(\d{1,4}\.\d{2})(\-?\d{1,3}\.\d{2})(.*?%)\n/\n$1 == $2 == $3 == $4\n/ig;

時々機能しますが、そうでない場合もあります。なぜこれが必要なのかわかりません。(以下の出力例の二重の等号は、フィールドの分割をより見やすくするために使用されています。)

Fishery, Agriculture & Forestry == 243.45 == -1.91 == -0.78%
Mining360.74-4.15-1.14%
Construction == 465.36 == -1.01 == -0.22%
Foods783.2511.281.46%

マイナス記号は、インデックスの価格にマイナスの変化が見られたインデックスにとって問題だと思いましたが、マイナス記号にもかかわらず機能する場合があります.

Q. 以下に示す最終的な正規表現がフィールドを一貫して分割できないのはなぜですか?

サンプルコードは次のとおりです。

#!/usr/bin/perl -w
use strict;
use LWP::Simple;
use HTML::Tree;

my $url_full = "http://www.tse.or.jp/english/market/STATISTICS/e06_past.html";

my $content = get($url_full);
# get dates:
(my @dates) = $content =~ /(?<=dateFormat\(')\d{4}\/\d{2}\/\d{2}(?='\))/g;
foreach my $date (@dates) { # convert to yyyy-mm-dd
    $date =~ s/\//-/ig;
}
my $tree = HTML::Tree->new();
$tree->parse($content);
my $mystr = $tree->as_text;

$mystr =~ s/\xA0//gi; # remove non-breaking spaces
# remove first chunk of text:
$mystr =~
  s/^(TSE.*?)IndustryIndexChange ?/IndustryIndexChange\n$dates[0]\n\n/gi;
$mystr =~ s/IndustryIndexChange ?/IndustryIndexChange/ig;
$mystr =~ s/IndustryIndexChange/Industry Index Change\n/ig;
$mystr =~ s/% /%\n/gi; # percent symbol is market for end of line
# indicate breaks between days:
$mystr =~ s/Stock.*?IndustryIndexChange/\nDAY DELIMITER\n/gi;
$mystr =~ s/Exemption from Liability.*$//g; # remove boilerplate at bottom

# and here's the problem regex...
# try to split it:
$mystr =~
  s/\n(.*?)(\d{1,4}\.\d{2})(\-?\d{1,3}\.\d{2})(.*?%)\n/\n$1 == $2 == $3 == $4\n/ig;

print $mystr;
4

3 に答える 3

2

問題は\n、正規表現の最初と最後に両方あることです。

次のようなことを考えてみましょう:

$s = 'abababa';
$s =~ s/aba/axa/g;

の重複しないオカレンスが 2 つしかないため、 ではなくに設定さ$sれます。axabaxa axaxaxaaba

于 2012-02-08T12:55:07.680 に答える
2

それは他のすべてをやっているようです。

私の推測では、あなたのレコードは\nそれらの間にシングルがありますが、あなたのパターンは . で始まり . で終わります\n。したがって、最初の一致の決勝では、2 番目の一致で 2 番目のレコードを見つけるために必要な が\n消費されます。\n最終的な結果は、1 つおきのレコードを取得することです。

^パターンを$( and の代わりに\n) and でラップし、 でフラグ\nを使用する方がよい場合があります。ms///

于 2012-02-08T12:53:40.130 に答える
0

私の解釈(疑似コード) -

one   = [a-zA-Z,& ]+
two   = \d{1,4}.\d\d
three = <<two>>
four  = <<two>>%

regex = (<<one>>)(<<two>>)(<<three>>)(<<four>>)
      = ([a-zA-Z,& ]+)(\d{1,4}.\d\d)(\d{1,4}.\d\d)(\d{1,4}.\d\d%)

ただし、HTML 形式の「構造化」データが既に表示されています。これを利用してみませんか?

perl での HTML 解析は、perlでの DOM ベースの解析用に MOJO を参照します。重大なパフォーマンス上の理由がない限り、このようなアプローチを強くお勧めします。

于 2012-02-08T13:21:49.550 に答える