Скрипт для построения HTML-страницы из извлеченных DIV из других HTML-страниц - PullRequest
1 голос
/ 31 июля 2009

У меня есть набор отчетов HTML, каждый из которых содержит два элемента DIV с определенными идентификаторами, которые мне нужно вырезать и скомпилировать в общий сводный отчет (опять же, файл HTML).

Вначале я думал, что это идеальная работа для сценария Perl, однако у нас нет современных внутренних навыков Perl (мы - магазин .NET C #).

Мысли и предложения о рекомендуемых подходах приветствуются ...

Ответы [ 3 ]

4 голосов
/ 31 июля 2009

Используйте подходящий HTML-парсер; HTML :: Parser для Perl, и я уверен, что есть несколько для C #.

2 голосов
/ 31 июля 2009

Используя Perl, HTML :: TokeParser и HTML :: Template могут помочь. Вот краткий пример:

#!/usr/bin/perl

use strict;
use warnings;

use HTML::TokeParser;
use HTML::Template;

use Data::Dumper;

my ($html_file) = @ARGV;

open my $html_handle, '<:utf8', $html_file
    or die "Cannot open '$html_file': $!";

my $parser = HTML::TokeParser->new( $html_handle );

my @divs;

while ( my $tag = $parser->get_tag('div') ) {
    my $attr = $tag->[1];
    next unless ref $attr eq 'HASH';
    next unless defined( my $id = $attr->{id} );
    next unless $id eq 'div1' or $id eq 'div2';

    my $div = $tag->[-1];
    my $in_wanted = 1;

    while ( $in_wanted ) {
        my $token = $parser->get_token;
        if ( $token->[0] eq 'T' ) {
            $div .= $token->[1];
        }
        else {
            $div .= $token->[-1];
        }
        my ($type, $name) = @$token[0, 1];
        if ( $name eq 'div' ) {
            $in_wanted += $type eq 'S' ?  1
                        : $type eq 'E' ? -1
                        : 0;
            next;
        }
        if ( $type eq 'E' and $name eq 'html' ) {
            warn "Warning: Reached the end of '$html_file'\n";
            last;
        }
    }

    push @divs, {DIV => $div};
}

print output( @divs );

sub output {
    my $tmpl_html = <<EO_TMPL;
<html>
<body>
<TMPL_LOOP DIVS>
    <TMPL_VAR DIV>
</TMPL_LOOP>
</body>
</html>
EO_TMPL
    my $tmpl = HTML::Template->new(
        scalarref => \$tmpl_html,
    );
    $tmpl->param( DIVS => \@_ );
    return $tmpl->output;
}
1 голос
/ 31 июля 2009

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

Если ваш div:

<div id="findme">
    <!-- No other divs here! -->
</div>

Тогда вы можете использовать регулярное выражение (просто будьте осторожны с жадностью), более элегантную версию этого:

<div id="findme">(.*?)</div>

примечание: я почти уверен, что регулярное выражение не запустится, это было давно!

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

Что-то вроде , этот учебник может быть полезен. Эти парсеры, вероятно, позволят вам точно извлечь данные, заключенные в тег, такой как ваш div.

Вы также можете использовать C # HTML-парсер , все они выполняют аналогичную работу. Просто просмотрите документацию, чтобы убедиться, что они не просто строят деревья, и позволяют вам получить смещения символов для вложенных данных div (чтобы их можно было извлечь) или разрешить доступ к этим данным.

...