如何使用 scraper crate 获取元素的内部文本?

use*_*783 3 web-scraping rust

我正在使用该scraper库来解析 HTML 文档并查找 ID 的节点foo

我想使用这个节点进行进一步的操作。对于这个例子,我试图通过类联系一些嵌套的孩子inner并检索innerText这些孩子的。

use scraper::{Html, Selector};

fn main() {
    let html = String::from(
        r#"
      <html>
        <head>
          <title>Test</title>
        </head>
        <body>
          <div id="foo"><div></div><div><div></div><div class="inner"><span>x<div>yo</div></span></div></div></div>
        </body>
      </html>
    "#,
    );

    let parsed_html = Html::parse_document(&html);
    let fragment = parsed_html
        .select(&Selector::parse("body").unwrap())
        .next()
        .unwrap();
    let foo = fragment
        .select(&Selector::parse("div#foo").unwrap())
        .next()
        .unwrap();

    let text = foo
        .children()
        .nth(1)
        .unwrap()
        .children()
        .nth(1)
        .unwrap()
        .children()
        .map(|child| child.value())
        .collect::<Vec<_>>();

    println!("{:?}", text);
}
Run Code Online (Sandbox Code Playgroud)

我的Cargo.toml文件:

[package]
name = "scraper"
version = "0.1.0"
authors = ["foo@bar"]
edition = "2018"

[dependencies]
scraper = "0.12.0"
Run Code Online (Sandbox Code Playgroud)

的输出rustup show

Default host: x86_64-apple-darwin
rustup home:  /Users/foobar/.rustup

stable-x86_64-apple-darwin (directory override for '/Users/foobar')
rustc 1.43.1 (8d69840ab 2020-05-04)

Run Code Online (Sandbox Code Playgroud)

控制台打印出[Element(<span>)]这是我在元素上调用方法的映射函数的结果value

我期待的结果是xyo

crate是否scraper有一些方法可以像我想要的那样提取文本,或者我是否必须创建某种递归函数?

我知道这段代码很容易出错,我将使用该match运算符来处理文档中不存在某些节点的情况。现在我只关注如何获取innerText子节点上的属性。

Ten*_*Ten 5

scraper有一种提取文本的方法:ElementRef::text

从通话中实现您想要的效果的一种方法.children()是:

...
.children()
.filter_map(|child| ElementRef::wrap(child))
.flat_map(|el| el.text())
.collect::<Vec<_>>(); // Or `.collect::<String>()` if you want xyo concatenated
Run Code Online (Sandbox Code Playgroud)

但是,根据您的示例,我觉得您可能希望使用选择器直接获取ElementRef与您的目标相对应的 s ,而不是使用大量.children()s 进行工作:

let inner: String = parsed_html
    .select(&Selector::parse("body div#foo:nth-child(1):nth-child(1)").unwrap()) // or "body div#foo div.inner"
    .flat_map(|el| el.text())
    .collect();
Run Code Online (Sandbox Code Playgroud)

这看起来更接近文档中的内容scraper