如何使用 html5ever 解析页面并找到所有链接?
How do I parse a page with html5ever and find all the links?
我想用 html5ever 解析字符串格式的 HTML 并找到这个 HTML 中的所有链接。我知道 ,但是 RcDom
不存在了。
您必须创建一个实现 TokenSink
的结构,然后创建一个新的 Tokenizer
,其中您的结构是 sink
。当使用 Tokenizer::feed()
解析时,它将通过您的 TokenSink
.
传递所有标记
此代码改编自 html5ever examples,因此已获得 Apache/MIT 许可。 html5ever 是一个为浏览器构建的复杂库,它显示 - API 似乎是为适应 UTF-8 以外的编码而设计的。
此代码仅从标准输入解析。如果你想按原样使用它,管道 curl
就像这样 curl | cargo run
。
当我这样做时,我得到类似
的输出
link to: #
link to: https://whosebug.com
link to: #
link to: /teams/customers
...
extern crate html5ever;
use std::default::Default;
use std::io;
use html5ever::tendril::*;
use html5ever::tokenizer::BufferQueue;
use html5ever::tokenizer::{StartTag, TagToken};
use html5ever::tokenizer::{Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts,};
use html5ever::interface::QualName;
use html5ever::{ns, namespace_url, LocalName};
#[derive(Copy, Clone)]
struct TokenPrinter {}
impl TokenSink for TokenPrinter {
type Handle = ();
fn process_token(&mut self, token: Token, _line_number: u64) -> TokenSinkResult<()> {
let link_name = QualName::new(
None,
ns!(),
LocalName::from("href"),
);
match token {
TagToken(tag) => {
if tag.kind == StartTag && tag.name.to_string()=="a" {
let attrs = tag.attrs;
for attr in attrs {
if attr.name == link_name {
println!("link to: {}", attr.value);
}
}
}
},
_ => {
},
}
TokenSinkResult::Continue
}
}
fn main() {
let sink = TokenPrinter {};
let mut chunk = ByteTendril::new();
io::stdin().read_to_tendril(&mut chunk).unwrap();
let mut input = BufferQueue::new();
input.push_back(chunk.try_reinterpret::<fmt::UTF8>().unwrap());
let mut tok = Tokenizer::new(
sink,
TokenizerOpts::default(),
);
let _ = tok.feed(&mut input);
assert!(input.is_empty());
tok.end();
}
我想用 html5ever 解析字符串格式的 HTML 并找到这个 HTML 中的所有链接。我知道 RcDom
不存在了。
您必须创建一个实现 TokenSink
的结构,然后创建一个新的 Tokenizer
,其中您的结构是 sink
。当使用 Tokenizer::feed()
解析时,它将通过您的 TokenSink
.
此代码改编自 html5ever examples,因此已获得 Apache/MIT 许可。 html5ever 是一个为浏览器构建的复杂库,它显示 - API 似乎是为适应 UTF-8 以外的编码而设计的。
此代码仅从标准输入解析。如果你想按原样使用它,管道 curl
就像这样 curl
。
当我这样做时,我得到类似
link to: #
link to: https://whosebug.com
link to: #
link to: /teams/customers
...
extern crate html5ever;
use std::default::Default;
use std::io;
use html5ever::tendril::*;
use html5ever::tokenizer::BufferQueue;
use html5ever::tokenizer::{StartTag, TagToken};
use html5ever::tokenizer::{Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts,};
use html5ever::interface::QualName;
use html5ever::{ns, namespace_url, LocalName};
#[derive(Copy, Clone)]
struct TokenPrinter {}
impl TokenSink for TokenPrinter {
type Handle = ();
fn process_token(&mut self, token: Token, _line_number: u64) -> TokenSinkResult<()> {
let link_name = QualName::new(
None,
ns!(),
LocalName::from("href"),
);
match token {
TagToken(tag) => {
if tag.kind == StartTag && tag.name.to_string()=="a" {
let attrs = tag.attrs;
for attr in attrs {
if attr.name == link_name {
println!("link to: {}", attr.value);
}
}
}
},
_ => {
},
}
TokenSinkResult::Continue
}
}
fn main() {
let sink = TokenPrinter {};
let mut chunk = ByteTendril::new();
io::stdin().read_to_tendril(&mut chunk).unwrap();
let mut input = BufferQueue::new();
input.push_back(chunk.try_reinterpret::<fmt::UTF8>().unwrap());
let mut tok = Tokenizer::new(
sink,
TokenizerOpts::default(),
);
let _ = tok.feed(&mut input);
assert!(input.is_empty());
tok.end();
}