#web-crawler #multi-threaded #async #broad #rust

app crusty

在 crusty-core 上开发的快速且可扩展的宽域网络爬虫

15 个版本 (破坏性更新)

0.12.0 2021 年 6 月 6 日
0.10.0 2021 年 6 月 6 日

#595并发

每月 30 次下载

GPL-3.0 许可证

56KB
1.5K SLoC

crates.io Dependency status

Crusty - 优雅且可扩展的宽域网络爬虫

简介

宽域网络爬虫是通过从一组位置(urls)开始并跟随外部域的出站链接来遍历几乎无限的网络的活 动。只要它有指向外部域的出站链接,通常起点在哪里并不重要。

它提出了许多挑战,必须克服这些挑战才能获得一个稳定且可扩展的系统,《Crusty》试图解决其中的一些挑战,在享受 Rust 的乐趣的同时看看这里有什么;(;)

这个特定的实现可以用来快速获取可观察互联网的所有子集,例如,发现最受欢迎的域名/链接

基于 crusty-core 构建,该库处理网络爬取的所有低级方面

主要特性

  • 可配置性和可扩展性

    查看一个典型的 配置文件,其中包含一些有关可用选项的解释

  • 快速的单节点性能

    Crusty 使用在 tokio 上运行的绿色线程编写,因此即使在中等配置的 PC 上也能实现相当可观的单节点性能

    可以进行其他优化来进一步提高此性能(主要是更好的 HTML 解析,有些任务不需要完整的 DOM 解析,这个实现主要为了可扩展性和可配置性而进行完整的 DOM 解析)

    Crusty 具有小型、稳定和可预测的内存占用,通常受 CPU/网络限制。没有 GC 压力,没有内存争夺战。

  • 可扩展性

    每个 Crusty 节点本质上是一个独立的单元,我们可以并行运行数百个(当然是在不同的机器上),难点在于工作委派和域发现,这通过在 clickhouse 上构建的高性能碎片化队列结构来解决(啊!)。

    有人可能会想“clickhouse?什么鬼?!”但这个数据库非常快(同时提供丰富的查询功能、索引、过滤),所以看起来很合适。

    该想法基本上是一个巨大的分片表,其中每个域名(实际上是解析到的IP衍生)都属于某个分片(crc32(addr) % number_of_shards),现在每个Crusty实例可以读取所有这些分片中的唯一子集,同时可以写入所有分片(所谓域名发现)。

    在中等规模部署(<16节点)中,该系统如目前这样是可行的,尽管如果有人试图将其扩展到巨规模,可能需要动态分片管理器...

    在多节点设置中,存在域发现去重方面的额外挑战,- 目前我们在本地和在clickhouse(AggregatingMergeTree)中进行去重,但随着节点数量的增加,本地去重效率降低

    在大规模部署中,可能需要专门的去重层,或者可以尝试通过确保有足够的分片和足够的clickhouse实例来满足所需性能,简单地推卸相当多的去重工作到clickhouse

  • 基本礼貌

    虽然我们可以并行爬取数千个域名,但我们绝对应该限制每个域名的并发量,以避免对爬取网站造成压力,请参阅job_reader.default_crawler_settings.concurrency。此外,测试表明,许多完全不同的域名可以存在于同一个物理IP上...所以我们从不尝试从一个IP获取超过job_reader.domain_top_n个域名

    在访问页面之间引入延迟也是一个好习惯,请参阅job_reader.default_crawler_settings.delay

    支持robots.txt

  • 可观察性

    Crusty使用跟踪并在clickhouse中存储多个度量标准,我们可以用grafana观察它们——提供爬取性能的实时洞察

example

入门

  • 在开始之前

安装docker && docker-compose,请遵循以下说明

https://docs.docker.net.cn/get-docker/

https://docs.docker.net.cn/compose/install/

  • 玩一玩它
git clone https://github.com/let4be/crusty
cd crusty
# might take some time
docker-compose build
# can use ANY or even several(separated by a comma), example.com works too just has one external link ;)
CRUSTY_SEEDS=https://example.com docker-compose up -d

此外

  • 学习配置文件并根据您的需求进行调整,对于100mbit通道,有合理的默认值,如果您有更多/更少的带宽/处理器,您可能需要调整concurrency_profile

  • 要停止后台运行并保留爬取数据,请运行docker-compose down

  • 要运行并附加,并查看所有容器的实时日志(可以按Ctrl+c中止)CRUSTY_SEEDS=https://example.com docker-compose up

  • 要查看正在运行的容器,请运行docker ps(应该是3个 - crusty-grafanacrusty-clickhousecrusty

  • 要查看日志:请运行docker logs crusty


如果您决定通过cargo build手动构建,请记住 - release构建要快得多(默认是debug

在实际应用场景中,尤其是在高带宽通道上,Docker可能显得有些昂贵,因此直接运行或至少设置 network_mode = host 可能是个好主意。

外部服务依赖 - ClickHouse 和 Grafana

仅使用 docker-compose,这是推荐的方式来玩耍 Crusty

然而...

要创建/清理数据库,请使用此 SQL(必须提供给 ClickHouse 容器中的 clickhouse client -在上下文中):链接

Grafana 仪表板以 JSON 模型导出:链接

开发

  • 确保已安装 rustup:[https://rustup.rs/](https://rustup.rs/)

  • 确保已安装 pre-commit:[https://pre-commit.git-scm.cn/](https://pre-commit.git-scm.cn/)

  • 运行 ./go setup

  • 运行 ./go check 以运行所有 pre-commit 钩子,并确保一切准备就绪以便进行 git 操作

  • 运行 ./go release minor 以发布下一个 minor 版本到 crates.io

贡献

我愿意讨论/接受贡献,请使用 github issues,

欢迎 pull requests

依赖

~19–32MB
~513K SLoC