4 个版本
0.2.2 | 2023年3月29日 |
---|---|
0.2.1 | 2022年3月27日 |
0.2.0 | 2022年3月27日 |
0.1.0 | 2022年3月19日 |
426 在 解析实现
9,133 每月下载量
用于 7 个crate (6 直接)
96KB
1.5K SLoC
Texting Robots
Crate texting_robots
是一个用于解析 robots.txt
文件的库。该crate的关键设计目标是拥有一个针对数百万个网站的实际数据进行全面测试的测试套件。虽然 robots.txt
本身是一个简单的规范,但互联网的规模和复杂性揭示了每个可能的边缘情况。
要了解更多关于 robots.txt
规范的信息,一个好的起点是 谷歌如何解释robots.txt规范。
这个库不能保护你免受所有可能的边缘情况,但应该为你提供一个强大的起点,以确保你和你代码对互联网的整体贡献是积极的。
安装
您可以通过将此条目
[dependencies]
texting_robots = "0.2"
添加到您的 Cargo.toml
依赖项列表中来安装库。
使用概述
此crate通过 Robot
结构体提供简单的高级使用。
Robot
结构体负责消费 robots.txt
文件,处理内容,并决定给定的URL是否允许您的机器人访问。有关您的机器人爬取延迟以及可能存在的任何网站地图等附加信息也均可获取。
鉴于有许多选项和潜在的偏好,Texting Robots 不执行缓存或对 robots.txt
文件本身的 HTTP GET 请求。这一步骤由库的使用者负责。
use texting_robots::{Robot, get_robots_url};
// If you want to fetch a URL we'll find the URL for `robots.txt`
let url = "https://rust-lang.net.cn/learn";
let robots_url = get_robots_url(url);
// Then we fetch `robots.txt` from robots_url to parse as below
// A `robots.txt` file in String or byte format.
let txt = r"User-Agent: FerrisCrawler
Allow: /ocean
Disallow: /rust
Disallow: /forest*.py
Crawl-Delay: 10
User-Agent: *
Disallow: /
Sitemap: https://www.example.com/site.xml";
// Build the Robot for our friendly User-Agent
let r = Robot::new("FerrisCrawler", txt.as_bytes()).unwrap();
// Ferris has a crawl delay of one second per limb
// (Crabs have 10 legs so Ferris must wait 10 seconds!)
assert_eq!(r.delay, Some(10.0));
// Any listed sitemaps are available for any user agent who finds them
assert_eq!(r.sitemaps, vec!["https://www.example.com/site.xml"]);
// We can also check which pages Ferris is allowed to crawl
// Notice we can supply the full URL or a relative path?
assert_eq!(r.allowed("https://rust-lang.net.cn/ocean"), true);
assert_eq!(r.allowed("/ocean"), true);
assert_eq!(r.allowed("/ocean/reef.html"), true);
// Sadly Ferris is allowed in the ocean but not in the rust
assert_eq!(r.allowed("/rust"), false);
// Ferris is also friendly but not very good with pythons
assert_eq!(r.allowed("/forest/tree/snake.py"), false);
爬取注意事项
获取 robots.txt
要获取 robots.txt
,需要对该域名执行初始的HTTP GET请求。在处理HTTP状态码及其对 robots.txt
的影响时,建议参考谷歌的建议。
- 2xx(成功):尝试处理结果负载
- 3xx(重定向):遵循合理数量的重定向
- 4xx(客户端错误):假设除了以下之外没有爬虫限制
- 429 "请求过多":在合理的时间内重试(可能由 "Retry-After" 头部设置)
- 5xx(服务器错误):假设在修复之前不应爬取,并/或小心解释
即使指示“假设没有爬虫限制”,在请求之间使用小的抓取延迟也是合理且礼貌的。
始终设置用户代理
对于爬取 robots.txt
(以及一般而言),应在请求中包含用户代理。大多数爬取库都提供单行添加用户代理的功能。
ClientBuilder.new().user_agent("FerrisCrawler/0.1 (https://ferris.rust/about-this-robot)")...
除了尊重 robots.txt
之外,提供良好的用户代理为您和网站管理员之间提供了一条沟通渠道。
除了 robots.txt
规范和一般建议之外
texting_robots
提供了您安全且尊重爬取所需的大部分内容,但本身不是完整的解决方案。
例如,在请求特定网站的页面时,必须跟踪HTTP错误代码429(请求过多)。当看到429时,爬虫应减速,即使遵守 robots.txt
中设置的 Crawl-Delay,并可能使用服务器Retry-After头中设置的延迟。
更复杂的例子是多个域名可能依赖于相同的后端Web服务器。对于托管成千上万个域的产品或服务来说,这是一个常见的场景。如何公平地使用 Crawl-Delay
完全取决于最终用户(当使用HTTP错误代码429进行流量限制时,可能也取决于服务)。
为了防止不良输入,建议 Texting Robots 的用户也遵循谷歌的建议,并将输入限制为500千字节。这尚未在库级别完成,因为可能需要更大的输入,但可能会根据社区反馈重新考虑。
Texting Robots 在其他语言中的使用
虽然目前尚未专门支持除Rust以外的任何语言,但该库的设计旨在支持未来的语言集成。通过测试与朋友一起测试对Web的 robots.txt
规范的解释更容易。
鉴于 Texting Robots 仅依赖于字符串、浮点数和布尔值,因此提供通过Rust FFI实现的C API相对容易。没有原生抓取功能应确保库可以在各个平台、情况和国家/地区之间移植。
在 WASI(“WebAssembly系统接口”)上进行了概念验证,表明库可以顺利编译,并且在使用 Wasmer(LLVM后端)和 Wasmtime 运行时分别时,仅会经历50%或75%的速度惩罚。迄今为止尚未进行优化,可能还有低垂的果实可以收获。
有关详细信息,请参阅 wasi_poc.sh
。
测试
要运行大多数核心测试,只需执行以下命令:cargo test
。
单元和集成测试
为了检查文本机器人的行为是否符合robots.txt
规范,几乎所有来自谷歌的C++ robots.txt解析器和Moz的reppy的单元测试都已翻译并包含在内。
谷歌和Moz的解释在某些方面存在分歧。当这种情况发生时,作者尽可能多地依靠常识。
对于许多流行的域名,保存了特定域的robots.txt
,并针对这些文件编写了测试。
Common Crawl测试工具
为了确保在现实世界情况下,robots.txt解析器不会在超过3400万个robots.txt
响应的情况下崩溃,已通过文本机器人传递了这些响应。虽然这个测试不能保证正确处理robots.txt文件,但它确实确保解析器在实际操作中不太可能崩溃。
在这个过程中发现了许多有问题、无效、荒谬甚至对抗性的robots.txt
示例。
有关详细信息,请参阅Common Crawl测试工具。
模糊测试
在本地fuzz
目录中有一个模糊测试工具。该工具并不特别复杂,但通过利用字典引导模糊测试,确实使用了低级别的结构意识。该工具已经揭示了一个低级别的unwrap崩溃。
要运行
cargo fuzz run fuzz_target_1 -- -max_len=512 -dict=keywords.dict
注意
- 要运行
cargo fuzz
,需要夜间构建(即在fuzz
目录中运行rustup default nightly
) - 如果您有多个处理器,可以在
cargo run
之后添加--jobs N
使用Tarpaulin进行代码覆盖率分析
本项目使用Tarpaulin进行代码覆盖率报告。由于解析器和Robot结构相对较小,覆盖率很高。然而,单元测试对于确保行为正确性更为重要。
要获取未覆盖代码的行号,请运行
cargo tarpaulin --ignore-tests -v
许可
许可方式为以下之一
- Apache License,版本2.0(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可(LICENSE-MIT或http://opensource.org/licenses/MIT)
您可选择。
贡献
除非您明确说明,否则任何您有意提交以包含在本作品中的贡献,根据Apache-2.0许可证的定义,均应按上述方式双许可,不附加任何额外条款或条件。
依赖项
约5-7MB
~146K SLoC