Cargo.toml:
[dependencies]
hyper = "0.13.5"
hyper-tls = "0.4.1"
scraper = "0.12.0"
tokio = {version = "0.2.21", features = ["full"]}
hyper 用于http请求。
hyper-tls 用于https请求。
scarper 用于解析html,获取想要的特征数据。
hyper 最新版本已经使用异步接口,所以网上的很多例子都是错的。
流程:
新建Http(s)请求
生成HttpClient
使用HttpClient获取HTML数据
使用Scarper 解析HTML
代码参考(删减):
extern crate hyper;
extern crate hyper_tls;
extern crate scraper;
extern crate tokio;
extern crate rand;
use hyper::client::Client;
use hyper::Uri;
use hyper::body;
use hyper::body::HttpBody;
use hyper_tls::HttpsConnector;
use scraper::ElementRef;
use scraper::Html;
use scraper::Selector;
use std::fs::create_dir;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::collections::HashMap;
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
//新建Https请求
let https = HttpsConnector::new();
//构建Https Client
let client = Client::builder().build::<_, hyper::Body>(https);
let url = String::from("https://xxx.com");
//Http::get
let res = client
.get(hyper::Uri::from_str(url.as_ref()).unwrap())
.await?;
//读入数据
let bytes = body::to_bytes(res.into_body()).await?;
// Scraper 开始解析HTML
let document = Html::parse_document(String::from_utf8(bytes.to_vec()).unwrap().as_ref());
// Css 选择器 提取信息
let selector = Selector::parse("div.pimg-box").unwrap();
let selector_a = Selector::parse("a").unwrap();
let product_list : Vec<String> = Vec::new();
// 获取信息
for element in document.select(&selector) {
for element_a in element.select(&selector_a) {
let href = element_a.value().attr("href").unwrap();
product_list.push(href.to_string());
}
}
Ok(())
}
总结:Rust目前的包的质量参差不起,文档更新也并不完善。像HTML解析底层的htm5ever包,说明文档寥寥无几。所以使用了Scarper,但也遇到了问题,Scarper依赖html5ever底层的一个StrTedril默认声明是不能跨线程的。导致解析任务不能在多个线程中并发执行,极大影响了爬虫的爬取效率。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。