首页 > 解决方案 > 如何使用 Kuchiki 获取 HTML 文档的所有文本(script/style/noscript 标签除外)?

问题描述

我正在尝试获取 HTML 页面上的所有文本,不可见文本除外(例如:我不希望在 script/style/noscript 标记中使用文本)。

到目前为止,这是我想出的:

let parser = kuchiki::parse_html().one(content);
for child in parser.inclusive_descendants() {
    if let Some(el) = child.as_element() {
        let tag_name = &el.name.local;
        if tag_name == "script" || tag_name == "style" || tag_name == "noscript" {
            child.detach();
        }
    }
}
let text = parser.text_contents();
println!("{}", text);

这个想法是第一遍将删除任何script, style, 或noscript标签。然后我可以打电话text_contents来获取可见的文本。

但是,似乎text_contents仍在返回内联 Javascript。

我是否误解了 Kuchiki/html5ever API?

标签: htmlrusthtml5everkuchiki

解决方案


迭代器inclusive_descendants()似乎不喜欢迭代节点分离它们。

鉴于以下情况:

货运.toml

[dependencies]
kuchiki = "0.8.1"

main.rs

use kuchiki::traits::TendrilSink;

let content = "\
    <html>\
    <head></head>\
    <body>\
        <div>div </div>\
        <script type='text/javascript'>script </script>\
        <noscript>noscript </noscript>\
        <span>span</span>\
    </body>\
    </html>";

let parser = kuchiki::parse_html().one(content);

for child in parser.inclusive_descendants() {
    if let Some(el) = child.as_element() {
        println!("{}", el.name.local);
    }
}

// println!("{}", parser.text_contents());

我们确实得到了所有节点:

html
head
body
div
script
noscript
span

text_contents()在迭代它们像上面那样分离它们之后使用时,迭代器似乎在第一个分离节点之后失去了轨道:

div noscript span

它似乎也不取决于标签的类型,因为切换<noscript>and<script>标签的顺序给了我们:

div script span

我发现先收集节点分离节点似乎确实有效:

parser
    .inclusive_descendants()
    .filter(|node| {
        node.as_element().map_or(false, |e| {
            matches!(e.name.local.as_ref(), "script" | "style" | "noscript")
        })
    })
    .collect::<Vec<_>>()
    .iter()
    .for_each(|node| node.detach());

println!("{}", parser.text_contents());
div span

推荐阅读