我遇到了与我想要抓的网站有关的另一个问题。
基本上我从页面内容中剥离了大部分我不想要的内容,并感谢here已经设法隔离我想要的日期的一些帮助。尽管一些初始问题与不间断的空间相匹配,但大多数似乎都工作正常。但是,我现在对最终正则表达式有困难,最终正则表达式旨在将每行数据拆分为字段。每一行代表股价指数的价格。每行的字段是:
以下是拆分前的示例字符串: “渔业,农业和林业243.45-1.91-0.78%采矿360,74-4.15-1.14%建筑465.36-1.01-0.22%食品783.2511.281.46%纺织品和服装412.070.540.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;
答案 0 :(得分:2)
它似乎正在做其他每一个。
我的猜测是,您的记录之间只有一个\n
,但您的模式以\n
开头和结尾。因此,第一场比赛的最终\n
将消耗第二场比赛找到第二场比赛所需的\n
。最终结果是,它获得了所有其他记录。
最好不要在^
和$
(而不是\n
和\n
)中包装您的模式,并使用m
标记。 s///
。
答案 1 :(得分:2)
问题是你在正则表达式的开头和结尾都有\n
。
考虑这样的事情:
$s = 'abababa';
$s =~ s/aba/axa/g;
将$s
设置为axabaxa
,不 axaxaxa
,因为aba
只发生了两次非重叠事件。
答案 2 :(得分: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的形式呈现了“结构化”数据。为什么不利用这个呢?
HTML parsing in perl引用了MOJO 对于perl中基于DOM的解析,除非有严重的性能原因, 我强烈推荐这种方法。