使用 Perl 在 HTML 中查找网站图标

2024-03-23

我正在尝试使用 Perl 查找给定 URL 的网站图标(和变体)(我想避免使用外部服务,例如 Google 的网站图标查找器)。有一个 CPAN 模块 WWW::Favicon,但它已经有十多年没有更新了——在这十年里,“apple-touch-icon”等重要的变体已经取代了古老的“ico”文件。

我想我在 WWW::Mechanize 中找到了解决方案,因为它可以列出给定 URL 中的所有链接,包括<link>标题标签。但是,我似乎无法找到一种干净的方法来使用“find_link”方法来搜索rel属性。

例如,我尝试使用“rel”作为搜索词,希望它可能在那里,尽管文档中没有提及,但它不起作用。此代码返回有关无效“链接查找参数”的错误。

my $results = $mech->find_link( 'rel' => "apple-touch-icon" );
use Data::Dumper;
say STDERR Dumper $results;

我还尝试使用其他链接查找参数,但它们似乎都不适合搜索 rel 属性。

我能弄清楚如何做到这一点的唯一方法是迭代所有链接并查找像这样的 rel 属性:

my $results = $mech->find_all_links(  );

foreach my $result (@{ $results }) {
    my $attrs = $result->attrs();
    #'tag' => "apple-touch-icon"
    
    foreach my $attr (sort keys %{ $attrs }) {
        if ($attrs->{'rel'} =~ /^apple-touch-icon.*$/) {
            say STDERR "I found it:" . $result->url();
        }

        # Add tests for other types of icons here.
        # E.g. "mask-icon" and "shortcut icon."

    }

}

这可行,但看起来很混乱。有没有更好的办法?


这是我的做法Mojo::DOM https://docs.mojolicious.org/Mojo/DOM。获取 HTML 页面后,使用dom完成所有解析。由此,使用 CSS 选择器来查找感兴趣的节点:

link[rel*=icon i][href]

这个CSS选择器寻找link具有以下内容的标签rel and href同时标记。此外,我要求该值rel包含 (*=) “图标”,不区分大小写(i)。如果你想假设所有节点都有href,就离开吧[href].

一旦我有了链接列表,我就只提取其中的值href并将该列表转换为数组引用(尽管我可以用Mojo::Collection方法):

use v5.10;

use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new->max_redirects(3);

my $results = $ua->get( shift )
    ->result
    ->dom
    ->find( 'link[rel*=icon i][href]' )
    ->map( attr => 'href' )
    ->to_array
    ;

say join "\n", @$results;

到目前为止效果很好:

$ perl mojo.pl https://www.perl.org
https://cdn.perl.org/perlweb/favicon.ico

$ perl mojo.pl https://www.microsoft.com
https://c.s-microsoft.com/favicon.ico?v2

$ perl mojo.pl https://leanpub.com/mojo_web_clients
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-57x57-b83f183ad6b00aa74d8e692126c7017e.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-60x60-6dc1c10b7145a2f1156af5b798565268.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-72x72-5037b667b6f7a8d5ba8c4ffb4a62ec2d.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-76x76-57860ca8a817754d2861e8d0ef943b23.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-114x114-27f9c42684f2a77945643b35b28df6e3.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-120x120-3819f03d1bad1584719af0212396a6fc.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-144x144-a79479b4595dc7ca2f3e6f5b962d16fd.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/apple-touch-icon-152x152-aafe015ef1c22234133158a89b29daf5.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/favicon-16x16-c1207cd2f3a20fd50de0e585b4b307a3.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/favicon-32x32-e9b1d6ef3d96ed8918c54316cdea011f.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/favicon-96x96-842fcd3e7786576fc20d38bbf94837fc.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/favicon-128x128-e97066b91cc21b104c63bc7530ff819f.png
https://d3g6anj9jkury9.cloudfront.net/assets/favicons/favicon-196x196-b8cab44cf725c4fa0aafdbd237cdc4ed.png

现在,如果您发现更有趣的情况而您无法轻松为其编写选择器,那么问题就来了。假设不是所有的rel价值观中有“图标”。您可以通过指定用逗号分隔的多个选择器来获得更奇特的效果,这样您就不必使用实验性的不区分大小写标志:

link[rel*=icon][href], link[rel*=ICON][href]

或不同的值rel:

link[rel="shortcut icon"][href], link[rel="apple-touch-icon-precomposed"][href]

根据需要排列任意多个。

但是,您也可以在没有选择器的情况下过滤结果。使用 Mojo::Collection 的grep选择您想要的节点:

my %Interesting = ...;
my $results = $ua->get( shift )
    ->result
    ->dom
    ->find( '...' )
    ->grep( sub { exists $Interesting{ $_->attr('rel') } } )
    ->map( attr => 'href' )
    ->to_array
    ;

我还有很多例子Mojo::DOM in Mojo 网络客户端 https://leanpub.com/mojo_web_clients,我想我现在就添加这个例子。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Perl 在 HTML 中查找网站图标 的相关文章

  • Perl:名称“main::IN”仅使用一次,但实际上已使用

    我编写了一个读取文件的简短 Perl 脚本 看tmp txt 1 gene id XLOC 000001 gene name DDX11L1 oId 1 gene id XLOC 000001 gene name DDX11L1 oId 1
  • 如何将我的包导入分组到单个自定义包中?

    通常当我编写 perl 程序时 我曾经包含以下包 use strict use warnings use Data Dumper 现在 我想像这样 我不会为每个程序都包含所有这个包 为了那个原因我会将这些全部打包在我自己的包中 喜欢跟随 m
  • 如何使用 Perl 从纯文本中提取 URL?

    我需要 Perl 正则表达式来解析纯文本输入并将所有链接转换为有效的 HTML HREF 链接 我已经尝试了在网上找到的 10 个不同版本 但没有一个可以正常工作 我还测试了 StackOverflow 上发布的其他解决方案 但似乎都不起作
  • 我应该如何使用 Perl URI 类?

    我需要在 Perl 程序中处理一些 HTTP URL 但我怀疑应该如何处理URI https metacpan org module URI类帮助我 特别是 我想使用URI用于解析相对 URL 并获取其组件的类 然而 问题是 我需要一个可以
  • 当与不需要虚拟机的编译程序一起使用时,CGI 是否仍然很慢?

    当我学习 CGI 时 我了解到任何编程语言都可以用来将其输出挂钩到 http 响应消息 而它的输入是 http 请求消息 我读过的很多文章都在 Perl 的背景下讨论 CGI 这是因为 Perl 是与 CGI 结合使用的最常见的语言吗 我想
  • Perl:通过一次 MySQL 调用更新多行

    似乎这不可能 但嘿我不妨问一下 我可能是错的 想知道 perl 是否可以使用一个 MySQL 调用来更新多行 我正在使用 DBI 任何帮助或反馈将不胜感激 这可以通过 ASP 和 ASP net 在 MSSQL 中实现 所以想知道是否也可以
  • 如何在 Moose 中存储哈希值的哈希值?

    我想知道 在 Moose 中存储哈希值的最佳方式是什么 让我们以这样的哈希为例 my hash step1 gt extraction gt object1 analysis gt object2 step2 gt extraction g
  • 添加一个favicon到redmine主题

    redmine 使用位于的 favicon usr share redmine public favicon ico 我发现很多代码片段使用cd usr share redmine grep HR favicon app app helpe
  • Perl 字符串替换:匹配但不替换正则表达式的一部分

    假设我在 Perl 中有一个字符串 我正在尝试匹配并替换为以下内容 string s a zA Z find a zA Z replace g 如图所示 我想替换两侧被非字母字符包围的所有内容 但是 当我替换字符串时 我不想也替换这些字符
  • Perl - HTTP::代理捕获 XHR/JSON 通信

    网站http openbook etoro com main http openbook etoro com main 有一个实时提要 由 javascript 通过 XHR keep alive 请求生成 并以 gzip 压缩 JSON
  • 如何从 Perl 中的字符串中去除无效的 XML 字符?

    我正在寻找一种标准的 经过批准的 可靠的方法 可以在将字符串写入 XML 文件之前从字符串中删除无效字符 我在这里讨论的是包含退格键 H 和换页符等的文本块 There has成为执行此操作的标准库 模块函数 但我找不到它 我在用着XML
  • 使用 Perl 计算字符串中的连续字符数

    我有一个包含多个连续字符序列的字符串 例如 aaabbcccdddd 我想将其表示为 a3b2c3d4 到目前为止 我已经想出了这个 usr bin perl str aaabbcccdddd str s 1 1 g print str n
  • 多个与单个 Catalyst 应用程序

    我有多个作为 FCGI 运行的 Catalyst 应用程序 将它们整合为具有多个控制器的单个控制器是否有好处 Thanks Simone 内存 大概吧 我认为每台服务器至少要保留 15MB 左右 因此如果您在 3 台服务器上运行 3 个应用
  • 检测 perl 中声明的包变量

    Given package main our f sub f sub g 1 我怎样才能确定 f 但不是 g 已宣布 即兴的 我以为 main g SCALAR 可能是未定义的 但它是一个善意标量参考值 背景 我想将一个变量导入到main
  • CPAN shell 内存不足。在 Unix 上如何给它更多的内存?

    我得到一个Out of memory 所有安装的消息 我以前从未使用过 cpan 并且不太确定它是如何工作的 我做了一个ulimit在 cpan 目录中 结果是无限的 这是我正在看的内容 usr bin perl MCPAN e shell
  • 是否有用于 AES 的纯 Perl 模块?

    是否有用于 AES 的纯 Perl 模块 地穴 Rijndael PP http search cpan org dist Crypt Rijndael PP Rijndael 是底层算法AES https secure wikimedia
  • 从日志尾部提取匹配行后退出

    我使用范围运算符来提取日志文件的一部分 例如 tail F logfile perl ne print if b d 现在 一旦提取的部分匹配 我就尝试退出该过程 我尝试过 tail F logfile perl ne print if b
  • Term::ReadLine - 我需要点击向上箭头两次才能检索历史记录

    我正在使用 Term ReadLine 并遇到一个奇怪的问题 我需要点击向上箭头两次才能从 addhistory 中检索项目 这是我正在使用的脚本 use Term ReadLine my term Term ReadLine gt new
  • Perl 单元测试只针对模块,而不针对程序吗?

    我在网上找到的文档和我拥有的书 Perl测试 或者说或者建议 Perl 的单元测试通常是在创建模块时完成的 这是真的 有没有办法使用单元测试实际程序Test More和表兄弟姐妹 当然 您可以使用测试脚本测试 更多 http search
  • 在 FOR 循环中打印唯一值

    我有两个文件 myresult 和 annotation 两个文件中的数据似乎是范围 但事实并非如此 这就是为什么我无法将其存储在数组中 我需要使用拆分运算符 以便我可以在 for 循环中使用它并进行比较 现在我需要打印 i myresul

随机推荐