HTMLReader 2.2.1

HTMLReader 2.2.1

测试已测试
语言语言 Obj-CObjective C
许可证 NOASSERTION
发布日期上次发布2022年10月
SPM支持 SPM

Nolan Waite 维护。



  • Nolan Waite

HTMLReader

一个遵循 WHATWG HTML 规范 且包含 CSS 选择器 的 Objective-C 和 Foundation 中的 HTML 解析器。它解析 HTML 的方式就像浏览器一样。

Supports iOS, OS X, tvOS, and watchOS

用法

以下是一个快速示例:解析一个内联文档并找到加粗文本

import HTMLReader

let document = HTMLDocument(string: """
    <p>
        Ahoy there, <b>sailor</b>!
    </p>
    """)
print(document.firstNode(matchingSelector: "b")?.textContent ?? "")
// => sailor

操作文档稍微复杂一些,但完全可以做到。这里我们从第一个示例中取出文档并给段落包裹一个新的元素

if
    let p = document.firstNode(matchingSelector: "p"),
    let parent = p.parent
{
    let wrapper = HTMLElement(tagName: "div", attributes: ["class": "special"])
    let children = parent.mutableChildren
    children.insert(wrapper, at: children.index(of: p))
    p.parent = wrapper
}

print(document.innerHTML)
// => <html><head></head><body><div class="special"><p>\
//        Ahoy there, <b>sailor</b>!\
//    </p></div></body></html>

您可以保存文档为文件

let serialized = document.serializedFragment
let temp = FileManager.default.temporaryDirectory
let fileURL = temp.appendPathComponent("nifty.html", isDirectory: false)
do {
    try serialized.write(to: fileURL, atomically: true, encoding: .utf8)
} catch {
    print("Could not save nifty document", error)
}

最后,最复杂的示例:获取 HTMLReader 仓库的主页,并抓取项目的描述。(这只是示例;如果需要获取仓库的描述,GitHub 提供了一个出色的 API!)

@import HTMLReader;

// Load a web page.
NSURL *url = [NSURL URLWithString:@"https://github.com/nolanw/HTMLReader"];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:url completionHandler:
  ^(NSData *data, NSURLResponse *response, NSError *error) {
    NSString *contentType = nil;
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields];
        contentType = headers[@"Content-Type"];
    }
    HTMLDocument *home = [HTMLDocument documentWithData:data
                                      contentTypeHeader:contentType];
    HTMLElement *div = [home firstNodeMatchingSelector:@".repository-meta-content"];
    NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    NSLog(@"%@", [div.textContent stringByTrimmingCharactersInSet:whitespace]);
    // => A WHATWG-compliant HTML parser in Objective-C.
}] resume];

安装

您有多种选择

  • 将 Sources 文件夹中的文件复制到您的项目中。

  • 将以下行添加到您的 Cartfile 中

    github "nolanw/HTMLReader"

  • 将以下行添加到您的 Podfile 中

    pod "HTMLReader"

  • 将以下行添加到您的 Package.swift 中

    .package(url: "https://github.com/nolanw/HTMLReader", from: "2.1.6")

  • 在Xcode中,通过选择“文件 > Swift包 > 添加包依赖”来添加此包,并输入URL https://github.com/nolanw/HTMLReader

  • 克隆此仓库(可能将其添加为子模块),并将HTMLReader.xcodeproj添加到您的项目/工作区中。然后,将HTMLReader.framework添加到您的应用程序目标中。(或者,如果您正在针对iOS 8.0之前的版本:将libHTMLReader.a添加到您的应用程序目标中,并将"$(SYMROOT)/include"添加到应用程序目标的首选头文件搜索路径中。)

HTMLReader除了Foundation没有其他依赖。

为什么选择HTMLReader?

我需要像浏览器一样抓取HTML。在iOS上找不到一个不错的选择。

替代方案

libxml2 与iOS一起提供。它解析HTML 4的某些版本(?)并且不像现代浏览器那样处理新的/损坏的标记。

我遇到的其他Objective-C和Swift库(例如,FuzihppleKannaOno)使用libxml2并且继承了其缺点。

SwiftSoup 是Jsoup的Swift端口。我在创建HTMLReader时还不存在。(公平地说,Swift也尚未公开。)

还有诸如GumboHubbub 这样的C库,但您需要将数据在Objective-C或Swift之间 shuffle。(此外,Gumbo在HTMLReader进度很远后才公开。)

WebKit 与iOS一起提供,但它的HTML解析功能被视为私有API。我认为通过网页视图进行循环不适合解析HTML。而且我没有深入构建自己的WebCore副本。

Google Toolbox for Mac 会为HTML(例如,&amp;&)进行转义和反转义,但又不像是现代浏览器。例如,GTM不会反转义&#65(请注意缺少分号)。

CFStringTransform 通过(可逆的)kCFStringTransformToXMLHex 进行数字实体转换,但排除了命名实体。

它正常工作吗?

HTMLReader 不断运行 html5lib 的标记化和树结构构建测试,忽略对 <template> 的测试(该元素 HTMLReader 并未实现)。请注意,为了实际运行这些测试,您需要检出 HTMLReaderTests/html5lib Git 子模块。

HTMLReader 在 GitHub Actions 提供的 SDK 上持续构建和测试。它旨在支持 iOS 5.0、macOS 10.7、tvOS 9.0 和 watchOS 2.0,但尚未进行自动化测试(尽管如此,您可以提交问题!)。

鉴于上述内容:构建状态

HTMLReader 至少被一个已发布的应用程序使用:Awful.app

它有多快?

我不确定。

项目包含了名为 Benchmarker 的一个实用工具。它知道如何运行三个测试:

  • 解析一个大型 HTML 文件。在这种情况下,7MB 的单页 HTML 规范。
  • 在大型 HTML 文件中转义和反转义实体。
  • 运行大量 CSS 选择器。基本上是从 WebKit 性能测试 中复制而来。

对 HTMLReader 的更改不应导致这些基准测试速度变慢。理想情况下,更改应该使它们运行更快!

错误和功能请求

可以通过 问题追踪器 报告错误并请求功能。或者如果您更喜欢直接联系。

许可证

HTMLReader 处于公有领域。

致谢

HTMLReader 由 Nolan Waite 开发。

感谢 Chris Williams 贡献 CSS 选择器的实现。