Ориентация на отдельные элементы в HTML с использованием Perl и Mojo :: DOM в хорошо отформатированном HTML - PullRequest
0 голосов
/ 11 января 2019

Относительный начинающий с Perl, с моим первым вопросом здесь, пробуя следующее:

Я пытаюсь получить определенную информацию из большого набора онлайн-данных (Eur-Lex), где каждый HTML-документ представляет собой правильно сформированный HTML-код с постоянными элементами. Каждый HTML-файл идентифицируется своим номером Celex, который предоставляется в качестве аргумента скрипту (см. Мой код Perl ниже). Данные HTML выглядят так (показаны только те части, которые мне интересны):

<!-- 
 <blahblah>
< lots of stuff here, before the interesting part>
--> 

      <div id="PPClass_Contents" class="panel-collapse collapse in" role="tabpanel"
           aria-labelledby="PP_Class">
         <div class="panel-body">
            <dl class="NMetadata">
               <dt xmlns="http://www.w3.org/1999/xhtml">EUROVOC descriptor: </dt>
               <dd xmlns="http://www.w3.org/1999/xhtml">
                  <ul>
                     <li>
                        <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;DC_CODED=341&amp;lang=en">
                           <span lang="en">descriptor_1</span>
                        </a>
                     </li>
                     <li>
                        <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;DC_CODED=5158&amp;lang=en">
                           <span lang="en">descriptor_2</span>
                        </a>
                     </li>
                     <li>
                        <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;DC_CODED=7983&amp;lang=en">
                           <span lang="en">descriptor_3</span>
                        </a>
                     </li>
                     <li>
                        <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;DC_CODED=933&amp;lang=en">
                           <span lang="en">descriptor_4</span>
                        </a>
                     </li>
                  </ul>
               </dd>
               <dt xmlns="http://www.w3.org/1999/xhtml">Subject matter: </dt>
               <dd xmlns="http://www.w3.org/1999/xhtml">
                  <ul>
                     <li>
                        <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;CT_CODED=BUDG&amp;lang=en">
                           <span lang="en">Subject_1</span>
                        </a>
                     </li>
                  </ul>
               </dd>
               <dt xmlns="http://www.w3.org/1999/xhtml">Directory code: </dt>
               <dd xmlns="http://www.w3.org/1999/xhtml">
                  <ul>
                     <li>01.60.20.00 <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;CC_1_CODED=01&amp;lang=en">
                           <span lang="en">Designation_level_1</span>
                        </a> / <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;CC_2_CODED=0160&amp;lang=en">
                           <span lang="en">Designation_level_2</span>
                        </a> / <a href="./../../../search.html?type=advanced&amp;DTS_DOM=ALL&amp;DTS_SUBDOM=ALL_ALL&amp;SUBDOM_INIT=ALL_ALL&amp;CC_3_CODED=016020&amp;lang=en">
                           <span lang="en">Designation_level_3</span>
                        </a>
                     </li>
                  </ul>
               </dd>
            </dl>
         </div>
      </div>
   </div>

<!-- 
<still more stuff here>
--> 

Меня интересует информация, содержащаяся в идентификаторе div "PPClass_Contents", который состоит из 3 элементов:


    - EUROVOC descriptor:
    - Subject matter:
    - Directory code:

Исходя из приведенного выше HTML, я хотел бы получить дочерние элементы этих 3 основных элементов, используя Perl и Mojo, получив результат, аналогичный следующему (однострочный текстовый файл, 3 группы, разделенные вкладками, несколько дочерних элементов в Grup разделены символами канала, что-то вроде этого:


    CELEX_No "TAB" descriptor_1|descriptor_2|descriptor_3|descriptor_4|..|descriptor_n "TAB" Subject_1|..|Subject_n "TAB" Designation_level_1|Designation_level_2|Designation_level_3|..|Designation_level_n

Элементы "descriptors", "Subjects" и "Designation_levels" (дочерние элементы этих 3 основных групп) могут иметь значение от 1 до "n", число не является фиксированным и заранее неизвестно.

У меня есть следующий код, который распечатывает простой текст интересной части, но мне нужно обратиться к отдельным элементам и распечатать их в новом файле, как описано выше:


    #!/usr/bin/perl
    # returns "Classification" descriptors for given CELEX and Language

    use strict;
    use warnings;

    use Mojo::UserAgent;

    if ($#ARGV ne "1") {
        print "Wrong number of arguments!\n";
        print "Syntax: clookup.pl Lang_ID celex_No.\n";
        exit -1;
    }

    my $lang = $ARGV[0];   
    my $celex = $ARGV[1];
    my $lclang = lc $lang;

    # fetch the eurlex page

    my $ua = Mojo::UserAgent->new;
    my $dom = $ua->get("https://eur-lex.europa.eu/legal-content/$lang/ALL/?uri=CELEX:$celex")->res->dom;


    ################ let's extract interesting parts:


    my $text = $dom->at('#PPClass_Contents')->all_text;
    print "$text\n";

РЕДАКТИРОВАТЬ (добавлено): Вы можете попробовать мой Perl-скрипт, используя два аргумента:

  • lang_code ("DE", "EN", "IT" и т. Д.)

  • Номер Celex (например, E2014C0303, 52015BP2212, 52015BP0930 (48), 52015BP0930 (36), 52015BP0930 (41), E2014C0302, E2014C0301, E2014C0271, E2014C0134 10 * * 10 * 25 *.

Например (если вы назовете мой скрипт "clookup.pl"): $ perl clookup.pl EN E2014C0303

Итак, как я могу адресовать отдельные элементы (с неизвестным номером), как описано выше, используя Mojo :: DOM?

Или есть что-то более простое или более быстрое (с использованием Perl)?

1 Ответ

0 голосов
/ 11 января 2019

Вы на правильном пути. Во-первых, вам нужно понять HTML внутри вашего #PPClass_Contents. Каждый набор вещей находится в списке определений. Поскольку вас интересуют только тексты определений, вы можете искать непосредственно элементы <dd>.

$dom->at('#PPClass_Contents')->find('dd')

Это даст вам Mojo :: Collection , которую вы можете повторить с ->each. Мы передаем эту анонимную функцию, почти как обратный вызов.

$dom->at('#PPClass_Contents')->find('dd')->each(sub {
    $_; # this is the current element
});

Каждый элемент будет передан в эту подпрограмму, и на него можно ссылаться, используя переменную темы $_. Внутри есть <ul>, и каждый <li> содержит элемент <span> с нужным вам текстом. Итак, давайте найдем их.

$_->find('span')

На этом этапе мы можем напрямую построить столбец в вашем выводе. Давайте используем другую форму ->each, которая превращает Mojo :: Collection, возвращенную из ->find, в обычный список Perl. Затем мы можем использовать обычную операцию map для захвата каждого текстового узла <span> и join в строку.

 join '|', map { $_->text } $_->find('span')->each

Чтобы связать все это вместе, мы объявляем массив вне этой конструкции и вставляем в него число $celex в качестве первого столбца.

my @columns = ($celex);
$dom->at('#PPClass_Contents')->find('dd')->each(sub {
    push @columns, join '|', map { $_->text } $_->find('span')->each;
});

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

print join "\t", @columns;

Я сделал это с EN в качестве языка и $celex number 32006L0121 , которое поиск использовал в своем примере всплывающей подсказки. Результат таков:

32006L0121 маркетинговый стандарт | химический продукт | приближение законов | опасное вещество | научный отчет | упаковка | Европейское химическое агентство | маркировка Внутренний рынок - Принципы | Приближение законов | Технические барьеры | Окружающая среда | Защита потребителей Промышленная политика и внутренний рынок | Внутренний рынок: сближение законов | Опасные вещества

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...