1

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>
--> 

我对“PPClass_Contents” div id 中包含的信息感兴趣,它由 3 个元素组成:

    - EUROVOC 描述符:
    - 主题:
    - 目录代码:

基于上面的 HTML,我想获取这 3 个主要元素的子元素,使用 Perl 和 Mojo,得到类似的结果(单行文本文件,由制表符分隔的 3 个组,一个 grup 中的多个子元素被分隔通过管道字符,如下所示:

    CELEX_No "TAB" 描述符_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”元素(这三个主要组的子项)可以从 1 到“n”,数量不固定,也不事先知道。

我有以下代码,它确实打印出有趣部分的纯文本,但我需要处理各个元素并将它们打印在一个新文件中,如上所述:

    #!/usr/bin/perl
    # 返回给定 CELEX 和语言的“分类”描述符

    使用严格;
    使用警告;

    使用 Mojo::UserAgent;

    if ($#ARGV ne "1") {
        print "参数数量错误!\n";
        print "语法:clookup.pl Lang_ID celex_No.\n";
        退出-1;
    }

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

    # 获取 eurlex 页面

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


    ################ 让我们提取有趣的部分:


    我的 $text = $dom->at('#PPClass_Contents')->all_text;
    打印“$文本\n”;

编辑(添加):您可以使用两个参数尝试我的 Perl 脚本:

  • lang_code(“DE”、“EN”、“IT”等)

  • Celex 编号(例如:E2014C0303、52015BP2212、52015BP0930(48)、52015BP0930(36)、52015BP0930(41)、E2014C0302、E2014C0301、E2014C0271、E2014C0134)。

例如(如果您将我的脚本命名为“clookup.pl”): $ perl clookup.pl EN E2014C0303

那么,如何使用 Mojo::DOM 处理如上所述的单个元素(数量未知)?

或者,有没有更简单或更快的东西(使用 Perl)?

4

1 回答 1

1

你在正确的轨道上。首先,您需要了解#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数字32006L0121来完成此操作,搜索在其示例工具提示中使用了它。结果是这样的:

32006L0121 营销标准|化工产品|法律近似|危险品|科学报告|包装|欧洲化学品管理局|标签 内部市场-原则|法律近似|技术壁垒|环境|消费者保护 产业政策和内部市场|内部市场:近似法律法规|危险物质

于 2019-01-11T17:06:20.827 回答