Perl: почему это регулярное выражение веб-скребка работает непоследовательно?
Я столкнулся с другой проблемой, связанной с сайтом, который я пытаюсь очистить.
По сути, я удалил большую часть того, что мне не нужно, из содержимого страницы, и благодаря некоторой помощи, приведенной здесь, удалось выделить нужные мне даты. Кажется, что большинство из них работает нормально, несмотря на некоторые начальные проблемы, связанные с неразрывным пробелом. Однако теперь у меня возникают трудности с последним регулярным выражением, которое предназначено для разбиения каждой строки данных на поля. Каждая строка представляет цену индекса цены акций. Поля в каждой строке:
- Имя произвольной длины, состоящее из символов латинского алфавита, иногда запятой или амперсанда, без цифр.
- Число с двумя цифрами после десятичной точки (абсолютное значение индекса).
- Число с двумя цифрами после десятичной точки (изменение значения).
- Число с двумя цифрами после десятичной точки, за которым следует знак процента (процентное изменение значения).
Вот пример строки перед разделением: "Рыболовство, сельское и лесное хозяйство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,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%
Я думал, что знак минус был проблемой для тех индексов, которые видели отрицательное изменение цены индекса, но иногда это работает, несмотря на знак минус.
В. Почему последнее регулярное выражение, показанное ниже, не может последовательно разделить поля?
Пример кода приведен ниже.
#!/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;
3 ответа
Похоже, что делают все остальные.
Я думаю, что ваши записи имеют один \n
между ними, но ваш шаблон начинается и заканчивается \n
, Итак финал \n
в первом матче потребляет \n
что для второго матча нужно найти вторую запись. Конечным результатом является то, что он собирает все остальные записи.
Вам может быть лучше обернуть свой шаблон в ^
а также $
(вместо \n
а также \n
) и используя m
флаг на s///
,
Проблема в том, что у вас есть \n
как в начале, так и в конце регулярного выражения.
Рассмотрим что-то вроде этого:
$s = 'abababa';
$s =~ s/aba/axa/g;
это установит $s
в axabaxa
не axaxaxa
потому что есть только два непересекающихся aba
,
Моя интерпретация (псевдокод) -
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 в perl ссылается на MOJO для анализа на основе DOM в perl, и, если нет серьезных причин для повышения производительности, я настоятельно рекомендую такой подход.