19 个版本

0.7.0-beta.22024 年 7 月 6 日
0.6.4 2024 年 6 月 15 日
0.6.3 2024 年 3 月 16 日
0.5.1 2023 年 12 月 16 日
0.1.2 2021 年 11 月 20 日

134网页编程

每月 21 次下载

MIT 许可协议

455KB
11K SLoC

Skyscraper - 使用 XPath 进行 HTML 抓取

Dependency Status License MIT Crates.io doc.rs

Rust 库,用于使用 XPath 表达式抓取 HTML 文档。

该库为 0.x 版本,因为许多 XPath 功能仍有 todo! 调用。如果您遇到一个认为应该优先考虑的功能,请在 GitHub 上提交问题。

有关详细信息,请参阅 支持的 XPath 功能 部分。

HTML 解析

Skyscraper 有自己的 HTML 解析器实现。解析器输出一个树结构,可以手动通过父子关系进行遍历。

示例:简单的 HTML 解析

use skyscraper::html::{self, parse::ParseError};
let html_text = r##"
<html>
    <body>
        <div>Hello world</div>
    </body>
</html>"##;
 
let document = html::parse(html_text)?;

示例:遍历父子关系

// Parse the HTML text into a document
let text = r#"<parent><child/><child/></parent>"#;
let document = html::parse(text)?;
 
// Get the children of the root node
let parent_node: DocumentNode = document.root_node;
let children: Vec<DocumentNode> = parent_node.children(&document).collect();
assert_eq!(2, children.len());
 
// Get the parent of both child nodes
let parent_of_child0: DocumentNode = children[0].parent(&document).expect("parent of child 0 missing");
let parent_of_child1: DocumentNode = children[1].parent(&document).expect("parent of child 1 missing");
 
assert_eq!(parent_node, parent_of_child0);
assert_eq!(parent_node, parent_of_child1);

XPath 表达式

Skyscraper 能够解析 XPath 字符串并将它们应用于 HTML 文档。

以下是一个基本的 xpath 示例。有关更多示例,请参阅 文档

use skyscraper::html;
use skyscraper::xpath::{self, XpathItemTree, grammar::{XpathItemTreeNodeData, data_model::{Node, XpathItem}}};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let html_text = r##"
    <html>
        <body>
            <div>Hello world</div>
        </body>
    </html>"##;

    let document = html::parse(html_text)?;
    let xpath_item_tree = XpathItemTree::from(&document);
    let xpath = xpath::parse("//div")?;
   
    let item_set = xpath.apply(&xpath_item_tree)?;
   
    assert_eq!(item_set.len(), 1);
   
    let mut items = item_set.into_iter();
   
    let item = items
        .next()
        .unwrap();

    let element = item
        .as_node()?
        .as_tree_node()?
        .data
        .as_element_node()?;

    assert_eq!(element.name, "div");
    Ok(())
}

支持的 XPath 功能

以下是目前支持的所有功能的非详尽列表。

  1. 基本 xpath 步骤:/html/body/div//div/table//span
  2. 属性选择://div/@class
  3. 文本选择://div/text()
  4. 通配符节点选择://body/*
  5. 谓词
    1. 属性://div[@class='hi']
    2. 索引://div[1]
  6. 函数
    1. fn:root()
    2. contains(haystack,needle)
  7. 前向轴
    1. 子元素:child::*
    2. 后代:descendant::*
    3. 属性:attribute::*
    4. DescendentOrSelf: descendant-or-self::*
    5. (更多即将推出)
  8. 反转轴
    1. 父级: parent::*
    2. (更多即将推出)
  9. 处理表达式: /html treat as node()

这应该涵盖了大多数XPath用例。如果您的用例需要未实现的功能,请在GitHub上提交一个问题。

依赖项

~2.2-3MB
~60K SLoC