Xpoint
   [напомнить пароль]

Парсинг простой HTML страницы, нужна помощь

Метки: [без меток]
[удл]
2011-04-15 01:13:38 [обр] Larry Wall[досье]
сообщение промодерировано

Всем доброго времени суток. Начал недавно изучать Perl. Столкнулся с парсингом HTML страницы.
Передача моих данных методом Post проходит успешно, php скрипт на сервере выдает нужный мне результат в следующем виде:

<br><font color=green>1. Date</font><font color=green>|01|04/2014|-site.com</font><br>
<strike><font color=red>2. Bad | 01|04|2999|</strike></font>

Нужен вывод двух этих значений без html кода в таком формате:

Date |01|04/2014|
Bad |01|04|2999|

С регулярными выражениями пока что не очень всё понятно.

Вот пример моего кода:

#!usr/bin/perl
$file="dates.txt";
open(RES,"<","$file");
@lol = <RES>;
close(RES);
foreach $dates(@lol){&next;}
sub next {$url = "http://site.net/date.php";
$lwp = LWP::UserAgent->new();
$lwp -> agent("Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4");
$request = $lwp->post($url, ["dates" => $dates, "Submit" => "Submit"]);

if($request->content =~ /(.*)/)

print $1;

Подскажите пожалуйста что нужно дописать что бы выводило мои результаты, спасибо заранее.

спустя 41 минуту [обр] Евгений Седов aka KPbIC(0/187)[досье]
next — плохое имя для функции.
спустя 3 часа 2 минуты [обр] Jared(0/26)[досье]

Larry Wall[досье] Во-первых, как сказал Евгений Седов aka KPbIC[досье] использовать имя next для своей функции недопустимо, так как это зарезервированное имя для оператора управления циклом. Во-вторых, приучитесь использовать прагму strict, это может сэкономить уйму времени на поиск ошибок. В-третьих, форматируйте ваш исходный код. Ну и в-четверых, вы привели не полный код =).

В вашем конкретном случае, нужно заменить все <br> на переводы строк, потом вырезать все теги и, наконец, вырезать все цифры, за которыми идет точка. Ах, ну и вдовершение в каждой строке последним символом должен остаться пайп | Примерно так:

#!/usr/bin/perl
use strict;
my $text = '<br><font color=green>1. Date</font><font color=green>|01|04/2014|-site.com</font><br>
<strike><font color=red>2. Bad |01|04|2999|</strike></font>';

$text =~ s|<br/?>|\n|g; # заменяем <br> и <br/> на перевод строки
$text =~ s/<.*?>//g; # вырезаем теги                             
$text =~ s/\d\.\s*//g; # убираем цифры с последующими точками и пробелами за ними
# убираем пробельные символы в начале и в конце выдачи
$text =~ s/^\s+//s; 
$text =~ s/\s+$//s;
$text =~ s/\n\n/\n/s; # убираем двойной перенос строки
$text =~ s/\|[^|]*$/|/gm; # В каждой строке убираем все, что идет за последним символом "|"

Но такое решение - решение из серии quick and dirty; Подойдет для выполнения одноразовой задачи. Но в общем случае, для разбора HTML регулярки не подходят, об этом говорилось и писалось тысячу раз. Нужно приводить HTML к XML и использовать соответствующие библиотеки для работы с последнем. Например, LibXML.

спустя 1 час 24 минуты [обр] Larry Wall[досье]
В вашем конкретном случае, нужно заменить все <br> на переводы строк, потом вырезать все теги и, наконец, вырезать все цифры, за которыми идет точка. Ах, ну и вдовершение в каждой строке последним символом должен остаться пайп |
Ну мне не обязательно удалять весь код, помогите написать регулярное выражение для этой части кода =)
спустя 3 часа 24 минуты [обр] Larry Wall[досье]
Тему можно сносить, решил всё это очень просто!
if и else
и не нужно не чего мудрить)
спустя 6 часов [обр] Роман Чемисов(16/350)[досье]
Larry Wall[досье]Так Вы поделитесь теперь с нами решением! Может быть кому-нибудь да и поможет в будущем.
спустя 1 час 28 минут [обр] stas[досье]

мне кажется, что для вашей задачи не нужно возиться с регулярными выражениями.
прочитайте вот тут седьмую главу:
http://www.dhs.net.ru/document......ILLY/books/perl3/lwp/index.htm

после этого, план примерно такой:

  1. передаёте контент от LWP::UserAgent на вход HTML::TokeParser
  2. конструкцией типа "получить текст, очищенный от тегов, до тега <br>" получаете всё что вам нужно.

регулярные выражения скорее всего будут выглядеть сложнее. а к коду как правило есть ещё требования комфортной дальнейшей поддержки.

спустя 6 минут [обр] stas[досье]

примерно как-то так.

use HTML::TokeParser;
... # тут из вашего кода запрос
my $content = $request->content();
my $stream = HTML::TokeParser->new( \$content );
my $line1 = $stream->get_trimmed_text( 'br' );
my $line2 = $stream->get_trimmed_text();

print "$line1\n$line2\n"

спустя 5 минут [обр] zloyrusskiy(0/3)[досье]
use common::sense;
use Mojo::DOM;


local $/ = '';
my $content = <DATA>;

my $dom = Mojo::DOM->new;

my $text = $dom->parse($content)->all_text;
# 1. Date|01|04/2014|-site.com2. Bad | 01|04|2999|

# убираем лишние пробелы
$text =~ s/\|\K\s+(?=\d+\|)//g;
# заменяем / на | в датах
$text =~ s/\|\d+\K\//\|/g;
# заменяем пробелы между словом и датой на 1 пробел(проверяем НЕ цифры)
$text =~ s/(?<=\D)\s*\|/ \|/g;
# получаем интересующие нас данные

my $result = join "\n",$text =~ /(\w+ (?:\|\d{2}){2}\|\d{4}\|)/g;

say $result;

__DATA__
<br><font color=green>1. Date</font><font color=green>|01|04/2014|-site.com</font><br>
<strike><font color=red>2. Bad | 01|04|2999|</strike></font>
Результат такой какой нужно.
спустя 1 час 20 минут [обр] Larry Wall[досье]

Всем спасибо кто ответил. Собственно вот и моё простое решение:

$request = $lwp->post($url, ["dates" => $dates, "Submit" => "Submit"]);{
if($request->content =~ /<font color=green>(.*)<\/font><br>/)
{print "Date $1\n";}
}{ 
if($request->content =~ /Bad(.*)<\/font><br>/)
{print "Bad $1\n";}}

Просто и коротко :)
хотя если нужно парсить большие страницы, такое не сгодится.

Powered by POEM™ Engine Copyright © 2002-2005