Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: разработка для Web > Как юзать модуль HTML::Parser в Perl?


Автор: Гость_s_a_s_h_a 5.8.2004, 20:05
Люди, расскажите, пожалуйста, как использовать модуль HTML::Parser для анализа HTML-кода.

Я смотрел документацию на http://search.cpan.org , но с моим очень плохим знанием англицкого ничего не понял, и экзамплы - единственное мое спасение - тоже не понял.

Мне надо получить информацию об имеющихся в HTML-документе формах, а именно name and action формы, списки input'ов, их types, names and values, а также аналогичную инфоррмацию об select'ах, textarea и т.п.

Всем, принявшим участие в развитии этой темы, заранее говорю спасибо.

Автор: ElectricalStorm 6.8.2004, 08:41
что нужно конкретно ?
Добавлено @ 08:41
вот тут снаяала посморите ... если не поможет то сюда ...

http://www.foo.be/docs/tpj/issues/vol5_1/tpj0501-0003.html

Автор: Гость_s_a_s_h_a 6.8.2004, 09:28
Посмотрел. Не помогло. Конкретно мне нужно следующее.

У меня есть строка, содержащая код HTML-страницы. Надо получить информацию о каждой форме на этой странице, т.е.:

форма 1
name="name" action="url"

input type="type_1" name="name_1" value="value_1"
input type="type_2" name="name_2" value="value_2"
select name="name" option_1 option_2 ..........
textarea name="name"

форма 2
name action
...............

Автор: Secandr 6.8.2004, 09:29
А самому руками разобрать при помощи регекспов?

Автор: Гость_s_a_s_h_a 6.8.2004, 09:56
Я извращенец в программировании, поэтому лучше использовать то, что сделали более опытные люди. Как-то давно уже пытался это сделать и ничего не получилось. Хотя... надо покопаться в архивах. Кажется я понял как это сделать. Но все равно. Как все-таки использовать этот модуль. Привидите код, пожалуйста, на каком-нибудь маленьком примере с реальными данными (в том смысле, что не так

$p = HTML::Parser->new( api_version => 3,
start_h => [\&start, "tagname, attr"],
end_h => [\&end, "tagname"],
marked_sections => 1,
);


где не понятно, что можно подставить и куда и как потом это использовать).

Автор: ElectricalStorm 6.8.2004, 10:20
вот
http://providerz.ru/articles/perl/html-parsing.html

и use Google !!!

Автор: Secandr 6.8.2004, 10:25
Если нужно парсить какой-то один файл или сайт, который изменяться не будет, то логичнее написать регексп. Будет быстрее и надёжнее.

Если нужно парсить разные сайты, формат которых неизвстен, то лучше использовать готовый модуль.

Автор: ElectricalStorm 6.8.2004, 10:35
Надежнее не факт что будет (это обуславливается не строгостью формата HTML )
.... и тем более не факт что быстрее ... (тем что регекспы работающие быстро еще надо научиться писать )

Автор: Гость_s_a_s_h_a 6.8.2004, 10:55
Парсить нужно разные сайты, формат которых неизвестен.
Спасибо за ссылку. Правда я ее уже видел. У меня маленький стаж программирования и поэтому есть некоторые трудности. В данном случае возникли следующие вопросы:

package ParseForm;

use strict;
use vars qw(@ISA $inrecord $inform);

@ISA = qw(HTML::Parser);
require HTML::Parser;

Что должны содержать переменные $inrecord $inform. И что именно делает эта часть кода.

use HTML::Parser;
$p = HTML::Parser -> new();

Это мне понятно, а то что выше нет.

Я также не понял, где вызываются процедуры start() and end(), а также почему в одном скрипте встречается два раза строка #!/usr/bin/perl -w


Автор: ElectricalStorm 6.8.2004, 10:58
я тоже посмотрел эту статью ....руки оторвать тому кто её писал...

посмотрите HTML::TokeParser он более простой ...

Автор: Гость_s_a_s_h_a 6.8.2004, 11:04
Спасибо за солидарность. Мало кто умеет доходчиво написать для ламеров и юзеров, а методом тыка иногда надоедает действовать.

Автор: ElectricalStorm 6.8.2004, 11:06
вот маленький примерчик набросал посмотрите
Код


#!/usr/bin/perl -w
     
use strict;
use HTML::TokeParser;

my $p = HTML::TokeParser->new(shift||"index.html");

while (my $token = $p->get_tag("form")) {
print $token->[0] ,"\n";
dumpHash( $token->[1] );
print "\n";

while (my $input_token = $p->get_tag("input")) {
 print $input_token->[0] , "\n";
 for (@$input_token) {
  if (ref eq "HASH" ) {
   dumpHash($_);
   print "\n";
  }
 }
}

#    my $text = $p->get_trimmed_text("/form");
#    print $text;

}

sub dumpHash  {
my $h = shift;
print $_." => ".$h->{$_},"\n" for (keys %{$h});
}


Автор: Гость_s_a_s_h_a 6.8.2004, 12:01
Посмотрел код. Ругается:

Can't call method "get_tag" on an undefined value at

while (my $token = $p->get_tag("form"))

а также на строки
while (my $token = $p->get_tag("a"))

while (my $token = $p->get_tag("title"))

и другие.

Автор: ElectricalStorm 6.8.2004, 12:05
а вы как вызывали ?
Добавлено @ 12:06
надо еще файл на вход

Автор: Гость_s_a_s_h_a 6.8.2004, 12:21
пример из мана:

use HTML::TokeParser;
$p = HTML::TokeParser->new($STR1);
if ($p->get_tag("title"))
{ my $title = $p->get_trimmed_text;
print "Title: $title\n";
}

$STR1 получаю из запроса к удаленному скрипту. Проверял - она содержит HTML-код

Автор: achmed 6.8.2004, 12:28
см.
perldoc HTML::Parser

там все понятно описано, с примерами

Автор: Гость_s_a_s_h_a 6.8.2004, 12:32
Нашел bug - если передаем строку для парсинга то надо поставить перед перед переменной \

use HTML::TokeParser;
$p = HTML::TokeParser->new(\$STR1);
if ($p->get_tag("title"))
{ my $title = $p->get_trimmed_text;
print "Title: $title\n";
}

Автор: ElectricalStorm 6.8.2004, 14:01
мой пример заработал у Вас ?

Автор: korob2001 6.8.2004, 16:20
Програ которую написал ElectricalStorm прекрасно работает только при вызове необходимо передать имя нужного html файла или в текущем каталоге должен быть файл с именем index.thml.

Вызывай примерно так:
C:\>perl myparser.pl home.html
Удачи.

Автор: Гость_s_a_s_h_a 6.8.2004, 16:39
Цитата(ElectricalStorm @ 6.8.2004, 14:01)
мой пример заработал у Вас ?

ElectricalStorm, не совсем. Если в документе больше одной формы, то он [скрипт] выдает, информацию о всех инпутах, но только об одном теге <form> - первом. Сейчас работаю над этой траблой. А ведь еще надо собрать инфу об опшинах тега <select>. Но главное начать. Спасибо, с вашей помощью у меня это получилось.

Автор: ElectricalStorm 6.8.2004, 16:50
вообщем то понятно почему она так делает ...
вложеным вайлом доходит до конца файла .... начиная с первого тега form

Автор: Гость_s_a_s_h_a 6.8.2004, 17:02
Это и мне понятно. Я уже немного модифицировал этот алгоритм. Теперь надо то что получилось в кучу собрать.

sub dumpHash
{
my $h = shift;
print $_." => ".$h->{$_},"<br>" for (keys %{$h});
}

use HTML::TokeParser;
$p = HTML::TokeParser->new(\$STR1);

my @tags= ("form","input","select","/select","texterea","/textarea","/form");

while (my $input_token = $p->get_tag(@tags))
{ print $input_token->[0] , "<br>";
for (@$input_token)
{
if (ref eq "HASH" )
{
dumpHash($_);
print "<br>";
}

}
}

Автор: ElectricalStorm 6.8.2004, 17:12
видите как легко получилось ....
а дальшле уже можно хоть чего с ним делать .... остальное можно без помощи модуля...

Код

use HTML::TokeParser;

my $p = HTML::TokeParser->new(shift || "index.html");
my @tags= ("form","input","select","/select","texterea","/textarea","/form");

while (my $input_token = $p->get_tag(@tags)) {
print $input_token->[3] , "\n";
}

Автор: Гость_s_a_s_h_a 8.8.2004, 14:00
Проблемы продолжаются. Теперь столкнулся со следующим недоразумением. Мне надо получить значение опшинов внутри тега <select>, используя функции get_text или get_trimmed_text, я их получаю, но они никак не разделены. Как это обойти. Вот кусок скрипта.

use HTML::TokeParser;
$p = HTML::TokeParser->new(\$STR1);

my @tags=("form","input","select","/select","texterea","/textarea","/form");

while (my $input_token = $p->get_tag(@tags))
{
if($input_token->[0] eq 'select')
{
$str = $p->get_trimmed_text("/select"); #получили строку с значениями опшинов никак не разделенными.

}
}

аналогичный результат, если $str = $p->get_text("/select");

и совсем пусто если $str = $p->get_trimmed_text; или $str = $p->get_text;

Если кто-то что-то понял, помогите, пожалуйста.

Автор: Гость_s_a_s_h_a 8.8.2004, 14:28
Меня осенило и я сделал это сам.

my @tags=("form","input","select","option","/select","texterea","/textarea","/form");

my $str2="";

while (my $input_token = $p->get_tag(@tags))
{
if($input_token->[0] eq 'select')
{ $str2="";}
if($input_token->[0] eq 'option')
{ my $str1 = $p->get_text;
$str2=$str2.":::".$str1;

}
}

Автор: aleksnn 2.5.2005, 23:43
Из google часто попадал сюда - учась парсить.
Теперь знаю как и скажу другим smile .
Делается так:

use HTML::Parser;
$parser = HTML::Parser->new(api_version => 3);
$parser ->handler(default => \&link_ext, 'tagname,text');
$parser->parse($html); # $html ваш файл

sub link_ext{
my ($tag, $text) = @_;
return if $tag eq "";
print "$tag => $text \n";
}

см perldoc HTML::Parser для просвещения.

Автор: player943 22.11.2006, 18:01
Граждане, раз уж есть такая тема то помогите с программой.
Сразу: rtfm читал.
Суть: надо используя HTML::TokeParser рассчитать частоту слов 
и фраз из двух-трех слов, исключая предлоги и знаки припинания, 
а также HTML теги и код JavaScript.

Вопрос: нужно перебирать все возможные тэги html или как просче ? 

Автор: Zukoff 4.7.2007, 14:48
Саша, ті решил заспамить гостевые книги? smile
лучше купи спамилку за 50 баксов

Автор: nitr 4.7.2007, 15:04
Ребят... тема 2006 года... давайте не флудить... и тем более оффтопить...

Автор: aleksnn 5.7.2007, 04:46
Цитата(Zukoff @ 4.7.2007,  14:48)
Саша, ті решил заспамить гостевые книги? smile
лучше купи спамилку за 50 баксов


Это вопрос ко мне? smile если что, то я не автор темы.

Сейчас скажу, что я тогда делал.

Я писал многопоточный менеджер закачек, висящий на сервере, который проходя по указанному сайту находил картинки, закачивал на сервер, пережимал размер, скдадывал результирующее изображение на другой хост по фтп, и высылал отчёт на емейл в архивированном виде.

Частично я сего монстра написал и раза  три использовал smile.


И чтобы сильно не офтопить отвечу на вопрос player943 как просче

Я когда-то подсчитывал количество полезных символов на странице примерно так

Открыл исходный текст нашёл там теги начала и конца полезного текста

Для этой страницы это
Код

<div class="postcolor">

</div>


сохранил страницу как index.htm.

запускаю такой код

Код

#!/usr/bin/perl -w

use strict;

my $Html;
my $file = 'c:\index.htm';
my $TagBegin ='<div class="postcolor">';
my $TagEnd ='</div';

open File,$file;
undef $/;
$Html=<File>;
while ($Html=~/$TagBegin(.*?)$TagEnd/g)
{
    my $a=$1;
    $a =~s/(<.*?>)|(&.*?;)//g; #режу мусорные теги, такие как br и спецсимволы
    print "$a\n\n";
}


который выдаёт мне десять строк полезных слов smile



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)