使用 Head-r 索引网页
Head-r 是一个 免费 Perl 程序,它递归地跟踪位于 (HTML) 网页 页面上的链接,这些页面托管在 HTTP 服务器上,并对用户感兴趣的链接执行 HEAD
请求。
该程序的预期用途是为以后选择性地 镜像 文件托管站点创建 URI 列表。
head-r [-v|--verbose] [-j|--bzip2|-z|--gzip] [--include-re=RE] [--exclude-re=RE] [--depth=N] [--info-re=RE] [--descend-re=RE] [-i|--input=FILE]... [-o|--output=FILE] [-P|--no-proxy] [-U|--user-agent=USER-AGENT] [-w|--wait=DELAY] [--] [URI]...
可以说,最重要的 Head-r 选项是 --info-re=
和 --descend-re=
,它们(通过 正则表达式)决定了哪些 URI 将被视为仅仅执行 HEAD
请求,以及 Head-r 将尝试从哪些 URI 中获取更多 URI。
对于以下示例,我们将使用 .
- 匹配任何非空字符串的正则表达式 - 允许 Head-r 对给定的两个 URI 都执行 HEAD
请求。
$ head-r --info-re=. \ -- http://example.org/ http://example.net/ http://example.org/ 1381334900 1 1270 200 http://example.net/ 1381334903 1 1270 200
字段以 ASCII HT(也称为 TAB)代码分隔,并且如下所示
- URI;
- 时间戳(以自系统依赖纪元以来的秒数计;另见 Unix 时间);
- 在考虑此 URI 时使用的递归深度;
- 响应的长度(以字节为单位)(根据
Content-Length:
HTTP 回复标头); - HTTP 状态代码 的回复。
对于以下示例,我们还将通过使用 --descend-re=/\$
选项来启用实际的递归(仍然在最大深度为 1 时)。
$ head-r --info-re=. --descend-re=/\$ \ -- http://example.org/ http://example.net/ http://example.org/ 1381337824 1 1270 200 http://www.iana.org/domains/example 1381337829 0 200 http://example.net/ 1381337830 1 1270 200
如您所见,在 http://example.org/ 中,Head-r 找到了另一个要考虑的 URI:http://www.iana.org/domains/example,它对其进行了跟踪并为此发出了 HEAD
请求。
很容易验证 http://example.net/ 实际上也引用了相同的 URI。但是,由于 Head-r 记得它处理过的 URI(以及该点的递归深度),因此没有发出其他请求。
现在考虑我们要递归遍历的资源引用了我们不感兴趣的 URI。对于以下示例,我们将使用比上面使用的 .
更具选择性的正则表达式。
$ head-r --{info,descend}-re=wikipedia\\.org/wiki/ \ -- http://en.wikipedia.org/wiki/Main_Page http://en.wikipedia.org/wiki/Main_Page 1381339589 1 61499 200 . . . http://en.wikipedia.org/w/api.php?action=rsd http://creativecommons.org/licenses/by-sa/3.0/ . . . http://meta.wikimedia.org/ http://en.wikipedia.org/wiki/Wikipedia 1381339589 0 609859 200 http://en.wikipedia.org/wiki/Free_content 1381339589 0 124407 200 . . .
(请注意,我们只是使用了 Bash {,}
扩展 将相同的正则表达式传递给 --info-re=
和 --descend-re=
。请确保调整到实际使用的 命令行解释器。)
在上面的输出中,一些 URI 没有任何通常的信息。这些 URI 是由 Head-r 找到的,但由于它们既不匹配“info”(--info-re=
)也不匹配“descend”(--descend-re=
)指定的正则表达式,因此没有对它们执行任何操作。但是,这些 URI 仍然输出,以防我们可能决定调整正则表达式本身。
--include-re=
和 --exclude-re=
正则表达式在所有其他正则表达式之前考虑,并且当前具有以下语义
- 包含正则表达式首先应用;如果 URI 与其中之一匹配,则将被考虑;
- 除非在上面的步骤中决定,否则将应用排除正则表达式;如果 URI 与其中之一匹配,则将不被考虑;
- 除非由上面的规则决定,否则 URI 将被考虑。
如果没有给出这些选项,Head-r 将考虑任何 URI。
以下示例利用这些选项来进一步限制 Head-r 的输出 对于上面的情况。
$ head-r --{include,descend}-re=wikipedia\\.org/wiki/ \ --{info,exclude}-re=. \ -- http://en.wikipedia.org/wiki/Main_Page http://en.wikipedia.org/wiki/Main_Page 1381341336 1 61499 200 http://en.wikipedia.org/wiki/Wikipedia 1381341337 0 609859 200 http://en.wikipedia.org/wiki/Free_content 1381341337 0 124407 200 http://en.wikipedia.org/wiki/Encyclopedia 1381341337 0 151164 200 http://en.wikipedia.org/wiki/Wikipedia:Introduction 1381341337 0 50687 200 . . .
Head-r 能够读取它自己的输出,因此为了避免发出重复的 HEAD
请求,以及为了发现要递归到其中的资源的 URI。
让我们重新审视 我们之前的一个例子,我们现在将对其进行修改,使其只对几个页面发出 HEAD
请求
$ head-r --output=state.a \ --info-re='/(Free_content|Wikipedia)$' \ --descend-re=wikipedia\\.org/wiki/ \ -- http://en.wikipedia.org/wiki/Main_Page $ grep -E \\s < state.a http://en.wikipedia.org/wiki/Main_Page 1381417546 1 61499 200 http://en.wikipedia.org/wiki/Wikipedia 1381417546 0 609859 200 http://en.wikipedia.org/wiki/Free_content 1381417546 0 124407 200 $
现在,为什么不包含更多页面,比如所有以 F
开头的名称的页面呢?
$ head-r \ --input=state.a --output=state.b \ --info-re=/wiki/F \ --descend-re=wikipedia\\.org/wiki/ $ grep -E \\s < state.b http://en.wikipedia.org/wiki/File:Diary_of_a_Nobody_first.jpg 1381417906 0 34344 200 http://en.wikipedia.org/wiki/File:Progradungula_otwayensis_cropped.png 1381417906 0 30604 200 http://en.wikipedia.org/wiki/File:AW_TW_PS.jpg 1381417907 0 33297 200 http://en.wikipedia.org/wiki/Fran%C3%A7ois_Englert 1381417907 0 87860 200 http://en.wikipedia.org/wiki/File:Washington_Monument_Dusk_Jan_2006.jpg 1381417907 0 83137 200 http://en.wikipedia.org/wiki/File:Walt_Disney_Concert_Hall,_LA,_CA,_jjron_22.03.2012.jpg 1381417907 0 67225 200 http://en.wikipedia.org/wiki/Frank_Gehry 1381417907 0 152838 200 $
请注意,虽然我们的 --info-re=
明显涵盖了 http://en.wikipedia.org/wiki/Free_content,但没有对该页面发出 HEAD
请求,因为我们的 --input=state.a
文件已经包含了相关信息。
此外,由于我们要让 Head-r 考虑的所有 URI 都已列在 state.a
中,因此没有必要在命令行中指定任何 URI。当 URI 来自命令行参数和--input=
文件时,来自命令行的 URI 将首先被考虑。
由于递归遍历大型网站可能会导致大型输出列表,因此 Head-r 提供对输出数据的压缩支持。
--bzip2
(-j
) 和 --gzip
(-z
) 选项选择用于输出文件(使用 --output=
指定或标准输出)的压缩方法。但是,如果启用了压缩并且输出到 终端 设备,Head-r 将退出并显示错误。
Head-r 透明地解压缩作为输入给出的文件 (--input=
),这得益于 IO::Uncompress::AnyUncompress 库。
有两个选项会影响 Head-r 使用的 HTTP 客户端的行为:--wait=
(-w
) 和 --user-agent=
(-U
)。
--wait=
选项指定两次连续 HTTP 请求之间等待的时间(以秒为单位)。默认值为约 2.7 秒。
--user-agent=
选项指定在 HTTP 请求中使用的 User-Agent:
头部的值,如果目标服务器根据该头部的值阻止访问,这可能会有用。默认值由字符串 HEAD-R-Bot/
、Head-r 的版本以及使用的 libwww-perl 库的标识组成。例如:HEAD-R-Bot/0.1 libwww-perl/6.05
。
请考虑通过 CPAN RT 报告 Head-r 软件中未列出的任何错误,https://rt.cpan.org/Public/Dist/Display.html?Name=head-r。本说明文档中的错误应报告到相应的 Wikibooks 讨论页面 - 或者您也可以自己修复它们!
对于任何其他自动检索工具,滥用 Head-r 造成第三方服务器过载并非不可能。建议用户在使用该工具时,尤其是在降低 --wait=
设置和将最大递归 --depth=
提高到超出合理值的范围时,考虑网络环境。
目前无法禁用 /robots.txt
文件处理。
代码只尝试从标记为 text/html
媒体类型 的内容中检索 URI,即使似乎可以相当容易地实现对 application/xhtml+xml
(以及可能其他几个 基于 XML 的类型,如 SVG)的支持。
首先将要检索 URI 的资源加载到内存中,而应该可以动态地处理它。
从 --input=
文件检索到的递归深度的处理方式可能有些直观,并且超出用户的控制范围。(尽管仍然可以使用第三方工具(如 AWK)编辑此类文件。)
该代码为长期存在的 Net::HTTP 错误 #29468 实现了一个简单的解决方法。
该代码的最新稳定版本可在 CPAN 获取。例如,请查看 https://metacpan.org/release/head-r 上的相应 Metacpan 页面。
最新开发版本可以从 Git 存储库下载,例如
$ git clone -- \ http://am-1.org/~ivan/archives/git/head-r-2013.git/ head-r
Gitweb 界面可在 http://am-1.org/~ivan/archives/git/gitweb.cgi?p=head-r-2013.git 获取。
Head-r 由 Ivan Shmakov 编写。
Head-r 是自由软件:您可以在自由软件基金会发布的 GNU 通用公共许可证的条款下重新发布和/或修改它,无论是许可证的第 3 版,还是(根据您的选择)任何更高版本。
本说明文档是在 Wikibooks 上进行的免费协作项目,根据 知识共享署名-相同方式共享许可证 (CC BY-SA) 3.0 版提供。