【问题标题】:How can I extract URL and link text from HTML in Perl?如何在 Perl 中从 HTML 中提取 URL 和链接文本?
【发布时间】:2010-09-20 05:46:07
【问题描述】:

我之前问过如何在 Groovy 中执行此操作。但是,由于所有 CPAN 库,现在我正在用 Perl 重写我的应用程序。

如果页面包含这些链接:

谷歌 苹果

输出将是:

谷歌,http://www.google.com 苹果,http://www.apple.com

在 Perl 中最好的方法是什么?

【问题讨论】:

    标签: html perl parsing url cpan


    【解决方案1】:

    我喜欢将pQuery 用于此类事情...

    use pQuery;
    
    pQuery( 'http://www.perlbuzz.com' )->find( 'a' )->each(
        sub {
            say $_->innerHTML . q{, } . $_->getAttribute( 'href' );
        }
    );
    

    还可以查看之前的 stackoverflow.com 问题Emulation of lex like functionality in Perl or Python 以获得类似的答案。

    【讨论】:

      【解决方案2】:

      HTML::LinkExtractor 优于 HTML::LinkExtor

      它可以同时给出链接文本和URL。

      用法:

       use HTML::LinkExtractor;
       my $input = q{If <a href="http://apple.com/"> Apple </a>}; #HTML string
       my $LX = new HTML::LinkExtractor(undef,undef,1);
       $LX->parse(\$input);
       for my $Link( @{ $LX->links } ) {
              if( $$Link{_TEXT}=~ m/Apple/ ) {
                  print "\n LinkText $$Link{_TEXT} URL $$Link{href}\n";
              }
          }
      

      【讨论】:

        【解决方案3】:

        看看HTML::LinkExtractorHTML::LinkExtor,它们是HTML::Parser 包的一部分。

        HTML::LinkExtractor 类似于 HTML::LinkExtor,除了获取 URL 之外,还获取链接文本。

        【讨论】:

        【解决方案4】:

        我们可以使用正则表达式来提取链接及其链接文本。这也是一种方式。

        local $/ = '';
        my $a = <DATA>;
        
        while( $a =~ m/<a[^>]*?href=\"([^>]*?)\"[^>]*?>\s*([\w\W]*?)\s*<\/a>/igs )
        {   
            print "Link:$1 \t Text: $2\n";
        }
        
        
        __DATA__
        
        <a href="http://www.google.com">Google</a>
        
        <a href="http://www.apple.com">Apple</a>
        

        【讨论】:

          【解决方案5】:

          如果您喜欢冒险并且想尝试不使用模块,那么这样的方法应该可以工作(根据您的需要进行调整):

          #!/usr/bin/perl
          
          if($#ARGV < 0) {
            print "$0: Need URL argument.\n";
            exit 1;
          }
          
          my @content = split(/\n/,`wget -qO- $ARGV[0]`);
          my @links = grep(/<a.*href=.*>/,@content);
          
          foreach my $c (@links){
            $c =~ /<a.*href="([\s\S]+?)".*>/;
            $link = $1;
            $c =~ /<a.*href.*>([\s\S]+?)<\/a>/;
            $title = $1;
            print "$title, $link\n";
          }
          

          我在这里可能做错了一些事情,但它在我编写后尝试的少数测试用例中有效(它不考虑 标签等)。

          【讨论】:

          • 你是大师,你为我节省了很多时间......非常感谢。
          【解决方案6】:

          以前的答案非常好,我知道我参加聚会迟到了,但这在 [perl] 提要中遇到了问题,所以......

          XML::LibXML 非常适合 HTML 解析,速度无与伦比。解析格式错误的 HTML 时设置 recover 选项。

          use XML::LibXML;
          
          my $doc = XML::LibXML->load_html(IO => \*DATA);
          for my $anchor ( $doc->findnodes("//a[\@href]") )
          {
              printf "%15s -> %s\n",
                  $anchor->textContent,
                  $anchor->getAttribute("href");
          }
          
          __DATA__
          <html><head><title/></head><body>
          <a href="http://www.google.com">Google</a>
          <a href="http://www.apple.com">Apple</a>
          </body></html>
          

          --产量--

               Google -> http://www.google.com
                Apple -> http://www.apple.com
          

          【讨论】:

            【解决方案7】:

            另一种方法是使用 XPath 来查询已解析的 HTML。在复杂情况下需要它,例如提取具有特定类的 div 中的所有链接。为此使用 HTML::TreeBuilder::XPath。

              my $tree=HTML::TreeBuilder::XPath->new_from_content($c);
              my $nodes=$tree->findnodes(q{//map[@name='map1']/area});
              while (my $node=$nodes->shift) {
                my $t=$node->attr('title');
              }
            

            【讨论】:

            • 另外,添加 $tree->delete 以避免内存泄漏。
            【解决方案8】:

            或者考虑增强 HTML::LinkExtor 来做你想做的事,并将更改提交给作者。

            【讨论】:

              【解决方案9】:

              请查看为此使用WWW::Mechanize 模块。它会为您获取您的网页,然后为您提供易于使用的 URL 列表。

              my $mech = WWW::Mechanize->new();
              $mech->get( $some_url );
              my @links = $mech->links();
              for my $link ( @links ) {
                  printf "%s, %s\n", $link->text, $link->url;
              }
              

              非常简单,如果您想导航到该页面上的其他 URL,它甚至更简单。

              Mech 基本上是一个对象中的浏览器。

              【讨论】:

              • 我冒昧地更改了打印语句以包含链接文本,按照 melling 的要求。
              【解决方案10】:

              Sherm推荐HTML::LinkExtor,这几乎是你想要的。不幸的是,它无法返回 标记内的文本。

              Andy 推荐WWW::Mechanize。这可能是最好的解决方案。

              如果您发现 WWW::Mechanize 不符合您的喜好,请尝试 HTML::TreeBuilder。它将从 HTML 中构建一个类似 DOM 的树,然后您可以搜索您想要的链接并提取您想要的任何附近的内容。

              【讨论】:

                【解决方案11】:

                HTML 是一种结构化标记语言,必须对其进行解析才能准确提取其含义。列出的模块 Sherm 将解析 HTML 并为您提取链接。如果您知道输入总是以相同的方式形成(不要忘记属性),那么基于正则表达式的临时解决方案可能是可以接受的,但解析器几乎总是处理结构化文本的正确答案。

                【讨论】:

                  猜你喜欢
                  • 2018-11-19
                  • 2012-11-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-03-26
                  • 2019-07-10
                  • 2023-03-16
                  相关资源
                  最近更新 更多