HTML::TreeBuilder внутри цикла

Я пытаюсь удалить все элементы таблицы из нескольких файлов HTML.

Следующий код отлично работает для одного файла, но при попытке автоматизировать процесс возвращает ошибку

не может вызвать метод look_down для неопределенного значения

У вас есть решение, пожалуйста?

Вот код:

use strict;
use warnings;

use Path::Class;
use HTML::TreeBuilder;

opendir( DH, "C:/myfiles" );
my @files = readdir(DH);
closedir(DH);

foreach my $file ( @files ) {

    print("Analyzing file $file\n");

    my $tree = HTML::TreeBuilder->new->parse_file("C:/myfiles/$file");

    foreach my $e ( $tree->look_down( _tag => "table" ) ) {
        $e->delete();
    }

    use HTML::FormatText;
    my $formatter = HTML::FormatText->new;
    my $parsed    = $formatter->format($tree);

    print $parsed;
}

1 ответ

Проблема в том, что вы кормите HTML::TreeBuilder все виды мусора в дополнение к HTML-файлам, которые вы намереваетесь. Как и любые файлы в открытом каталоге, readdir возвращает имена всех подкаталогов, а также псевдо-каталогов . а также .., Вы бы видели это в выводе из вашего print заявление

print("Analyzing file $file\n");

Один из способов исправить это - проверить, что каждое значение в цикле является файлом перед его обработкой. Что-то вроде этого

for my $file ( @files ) {

    my $path = "C:/myfiles/$file";
    next unless -f $path;

    print("Analyzing file $file\n");

    my $tree = HTML::TreeBuilder->new->parse_file($path);

    for my $table ( $tree->look_down( _tag => 'table' ) ) {
        $table->delete();
    }

    ...;
}

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

Это будет выглядеть примерно так. Вам бы пришлось настроить шаблон glob, если все ваши файлы не заканчиваются .html

for my $path ( glob "C:/myfiles/*.html" ) {

    print("Analyzing file $path\n");

    my $tree = HTML::TreeBuilder->new->parse_file($path);

    for my $table ( $tree->look_down( _tag => 'table' ) ) {
        $table->delete();
    }

    ...;
}

Строго говоря, имя каталога также может выглядеть *.html и если вы не доверяете своей файловой структуре, вы также должны проверить, что каждый результат glob файл перед его обработкой Но в обычных ситуациях, когда вы знаете, что в каталоге вы обрабатываете, что не нужно

Другие вопросы по тегам