#web-scraping #web #html #css #web-crawler

crabler-tokio

Crabs 的网页抓取器 - tokio 版本

2 个版本

0.1.29 2023 年 4 月 9 日
0.1.28 2023 年 4 月 9 日

#24 in #web-crawler

每月下载量 23

MIT 许可证

22KB
416

Crabler-Tokio - Crabs 的网页爬虫

CI Crates.io docs.rs MIT licensed

使用 Rust 编写的异步网页抓取器。

crabler 包移植。原始工作和作者可以在这里找到:https://github.com/Gonzih/crabler

crabler 和 crabler-tokio 之间的主要区别是我们替换了以下依赖

  • async_std -> tokio
  • surf -> reqwest

这样做的主要动机是更接近纯 Rust,并放弃对 libcurl 和 libssl 的要求。

cargo tree 输出减少了几个导入

  • crabler 有 488 个依赖项
  • crabler-tokio 有 350 个依赖项

功能

  • 完全基于 tokio
  • 基于 derive 宏的 API
  • 基于结构的 API
  • 有状态的抓取器(结构可以持有状态)
  • 下载文件的能力
  • 以异步方式调度导航作业的能力
  • 使用 reqwest 包进行 HTTP 请求

使用方法

将其添加到您的 Cargo.toml

[dependencies]
crabler-tokio = "0.1.0"

## Example

```rust,no_run
extern crate crabler;

use std::path::Path;

use crabler::*;
use reqwest::Url;

#[derive(WebScraper)]
#[on_response(response_handler)]
#[on_html("a[href]", walk_handler)]
struct Scraper {}

impl Scraper {
    async fn response_handler(&self, response: Response) -> Result<()> {
        if response.url.ends_with(".png") && response.status == 200 {
            println!("Finished downloading {} -> {:?}", response.url, response.download_destination);
        }
        Ok(())
    }

    async fn walk_handler(&self, mut response: Response, a: Element) -> Result<()> {
        if let Some(href) = a.attr("href") {
            // Create absolute URL
            let url = Url::parse(&href)
                .unwrap_or_else(|_| Url::parse(&response.url).unwrap().join(&href).unwrap());

            // Attempt to download an image
            if href.ends_with(".png") {
                let image_name = url.path_segments().unwrap().last().unwrap();
                let p = Path::new("/tmp").join(image_name);
                let destination = p.to_string_lossy().to_string();

                if !p.exists() {
                    println!("Downloading {}", destination);
                    // Schedule crawler to download file to some destination
                    // downloading will happen in the background, await here is just to wait for job queue
                    response.download_file(url.to_string(), destination).await?;
                } else {
                    println!("Skipping existing file {}", destination);
                }
            } else {
              // Or schedule crawler to navigate to a given url
              response.navigate(url.to_string()).await?;
            };
        }

        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    let scraper = Scraper {};

    // Run scraper starting from given url and using 20 worker threads
    scraper.run(Opts::new().with_urls(vec!["https://www.rust-lang.net.cn/"]).with_threads(20)).await
}

示例项目(原始 crabler 包)

Gonzih/apod-nasa-scraper-rs

依赖项

~9–24MB
~376K SLoC