Rust实战 Rust简单爬虫爬取豆瓣电影前250

1,036 阅读2分钟

0x00 开篇

当我们想从某些网站获取一些信息的时候,比如新闻、股票、电影数据等,最简单的方法是使用 API。但是如果网站没有提供免费的 API,我们只能借助爬虫了。本篇文章将简单介绍使用 Rust 来爬取 豆瓣前250电影

0x01 请求豆瓣

豆瓣 Top250 网站地址如下:

https://movie.douban.com/top250

我们使用 reqwest 这个库来请求 豆瓣Top250 网站。由于豆瓣的网站有防爬虫的机制,所以我们需要添加 ua

    // 请求豆瓣网址
    let url = "https://movie.douban.com/top250";
    let ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.64";
    let result = reqwest::ClientBuilder::new().user_agent(ua).build().unwrap().get(url).send().await.unwrap().text().await.unwrap();
    dbg!(result);

运行后,你会发现,整个豆瓣的 html 都打印了出来,看到这里已经成功一半了。

0x02 解析 Html

我们可以使用 scraper 来解析返回的结果,scraper 使用非常简单,类似于 js 解析 Dom

scraper简单介绍

我们可以将 html 字符串转为 document

use scraper::Html;
​
let html = r#"
    <!DOCTYPE html>
    <meta charset="utf-8">
    <title>Hello, world!</title>
    <h1 class="foo">Hello, <i>world!</i></h1>
"#;
​
let document = Html::parse_document(html);

也可以使用选择器。

use scraper::Selector;
​
let selector = Selector::parse("h1.foo").unwrap();
​
for element in document.select(&selector) {
    assert_eq!("li", element.value().name());
}

注意,这里我测试 select 方法等同于 js 中的 querySelectAll

解析豆瓣

我们接下来解析豆瓣的电影,将豆瓣电影的标题打印出来。

// 解析
    let document = scraper::Html::parse_document(result.as_str());
    let li_selector = scraper::Selector::parse(".grid_view > li > div > div > div > a > .title:first-child").unwrap();
    let movies = document.select(&li_selector).map(|x| x.inner_html());

解析的关键步骤主要是选择器 .grid_view > li > div > div > div > a > .title:first-child

0x03 完整代码

最后贴一下完整的代码吧。这里,我还是用了 tokio 这个库。

#[tokio::main]
async fn main() {
    // 请求豆瓣网址
    let url = "https://movie.douban.com/top250";
    let ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.64";
    let result = reqwest::ClientBuilder::new().user_agent(ua).build().unwrap().get(url).send().await.unwrap().text().await.unwrap();
​
    // 解析
    let document = scraper::Html::parse_document(result.as_str());
    let li_selector = scraper::Selector::parse(".grid_view > li > div > div > div > a > .title:first-child").unwrap();
    let movies = document.select(&li_selector).map(|x| x.inner_html());
    let mut index = 1;
    for title in movies {
        println!("{index}、{title}");
        index += 1;
    }
}

由于豆瓣每页只显示 25 条数据,所以最后会打印前 25条数据。

1、肖申克的救赎
2、霸王别姬
3、阿甘正传
4、泰坦尼克号
5、这个杀手不太冷
...省略后面的输出结果

0x04 小结

上面的代码是演示代码,在演示代码中使用了大量 unwrap,实际场景应用时请处理这些 Result。另外,这里只是简单介绍如何爬取静态网页,如果想要爬取动态网页,需要使用 thirtyfour (无头浏览器) 。