Exp*_*lls 11 rust hyper html5ever
我正在尝试解析HTTP请求的HTML响应.我正在使用hyper来处理请求,使用html5ever进行解析.HTML将非常大,我不需要完全解析它 - 我只需要从标签中识别一些数据,所以我更愿意流式传输它.从概念上讲,我想做的事情如下:
# bash
curl url | read_dom
/* javascript */
http.get(url).pipe(parser);
parser.on("tag", /* check tag name, attributes, and act */)
Run Code Online (Sandbox Code Playgroud)
到目前为止我想出的是:
extern crate hyper;
extern crate html5ever;
use std::default::Default
use hyper::Client;
use html5ever::parse_document;
use html5ever::rcdom::{RcDom};
fn main() {
let client = Client::new();
let res = client.post(WEBPAGE)
.header(ContentType::form_url_encoded())
.body(BODY)
.send()
.unwrap();
res.read_to_end(parse_document(RcDom::default(),
Default::default().from_utf8().unwrap()));
}
Run Code Online (Sandbox Code Playgroud)
看起来read_to_end我想调用读取字节的响应的方法,但我不清楚如何将它传递给HTML文档阅读器......如果这是可能的话.
说明parse_document要使用的文档,from_utf8或者from_bytes输入是否以字节为单位(即它).
看来我需要从响应中创建一个接收器,但这就是我被困住的地方.我也不清楚如何创建事件来监听标签启动,这是我感兴趣的.
我看过这个html5ever的例子似乎做了我想做的事情并且走了DOM,但是我不能让这个例子本身运行 - 要么它已经过时了,要么卷须/ html5ever太新了.这似乎也解析了整个HTML而不是流,但我不确定.
是否有可能对我们想要对这些库的当前实现做什么?
很抱歉缺少html5ever和tendril的类似教程的文档...
除非您100%确定您的内容是UTF-8,否则请使用from_bytes而不是from_utf8.它们返回一些实现的东西,TendrilSink允许您以递增方式(或不提供)提供输入.
该std::io::Read::read_to_end方法需要a &mut Vec<u8>,因此无法使用TendrilSink.
在最低级别,您可以TendrilSink::process每个&[u8]块调用一次方法,然后调用TendrilSink::finish.
为避免手动执行此操作,还TendrilSink::read_from需要采用的方法&mut R where R: std::io::Read.自hyper::client::Response实现以来Read,您可以使用:
parse_document(RcDom::default(), Default::default()).from_bytes().read_from(&mut res)
Run Code Online (Sandbox Code Playgroud)
超越你的问题,RcDom是非常小的,并且大部分存在是为了测试html5ever.我推荐使用Kuchiki.它具有更多功能(用于树遍历,CSS选择器匹配,......),包括可选的Hyper支持.
在你的Cargo.toml:
[dependencies]
kuchiki = {version = "0.3.1", features = ["hyper"]}
Run Code Online (Sandbox Code Playgroud)
在你的代码中:
let document = kuchiki::parse_html().from_http(res).unwrap();
Run Code Online (Sandbox Code Playgroud)