最直接方式是用 urlsession 的 datatask 异步加载网络 html,本地文件则用 string(contentsof:encoding:) 并确保路径正确;编码统一指定 .utf8,解析推荐 kanna 库。

用 URLSession 加载 HTML 字符串最直接
Swift 本身不带 HTML 解析器,读取 HTML 内容第一步是「拿到原始字符串」,而不是一上来就想着解析 DOM。绝大多数场景下,你真正需要的是从网络或本地文件加载 HTML 源码,再交给第三方库处理。
常见错误是试图用 String(contentsOf:) 直接读网络 URL——它只支持本地路径,遇到 http/https 会崩溃并抛出 NSURLErrorDomain error -1002(unsupported URL scheme)。
- 网络 HTML:必须用
URLSession的dataTask异步加载,别堵主线程 - 本地 HTML 文件:可用
String(contentsOf:encoding:),但要确保路径正确,比如Bundle.main.url(forResource: "index" , withExtension: "html") - 编码注意:HTML 常含 UTF-8 BOM 或 meta charset 声明,
String初始化时指定.utf8最安全,别依赖自动推断
解析 HTML 别自己写正则,用 Kanna 最省心
iOS/macOS 没有内置 HTML 解析 API,libxml2 太底层,XMLParser 又不认 HTML 的宽松语法。真实项目里,Kanna 是 Swift 生态中兼容性好、语法简洁的主流选择。
容易踩的坑是忽略 HTML 的 malformed 特性:比如缺少闭合标签、属性没引号、嵌套错乱——这些浏览器能容错渲染,但严格 XML 解析器会直接失败。而 Kanna 底层用的是 libxml2 的 HTML 模式,天生支持这类“脏数据”。
立即学习“前端免费学习笔记(深入)”;
- 安装:用 Swift Package Manager 添加
https://github.com/tid-kijyun/Kanna,别用 CocoaPods(已过时) - 加载后立即检查
doc?.description是否为空,空值代表解析失败,不是代码写错了,很可能是编码或文档结构问题 - 用
css("a[href]")比xpath("//a[@href]")更直观,但复杂筛选(如父元素限制)还是得切回 xpath
WKWebView 也能读 HTML,但仅限“已渲染后”的内容
如果你的目标不是源码,而是页面最终展示的文本、链接或结构化数据(比如等 JS 执行完再抓),WKWebView 是唯一可靠途径。但它不是“读取 HTML”,而是“运行 HTML 并提取结果”。
典型误用是把 loadHTMLString(_:baseURL:) 当作解析入口——它只是渲染,不提供 DOM 访问能力,除非你主动注入 JS。
- 必须等
webView(_: didFinishNavigation:)回调触发后,再用evaluateJavaScript(_:completionHandler:) - JS 脚本里别直接返回
document.body.innerHTML,大页面会卡顿;优先用document.querySelectorAll("h1, .title")拿具体节点再序列化 - 注意跨域限制:本地 HTML 文件(
file://)加载时,JS 无法发网络请求,也不能读取其他本地文件
本地 HTML 文件路径容易错在 Bundle 和沙盒混淆
很多人把 HTML 放进 Xcode 项目里就以为能直接读,结果 String(contentsOf:) 报 File not found。根本原因是没分清资源位置:Bundle 里的文件是只读的,Documents 或 tmp 下的才是可写沙盒路径。
另一个隐形坑是模拟器和真机行为不一致——某些旧版 Xcode 在模拟器里会把 bundle 资源映射到奇怪路径,导致 url(forResource:) 返回 nil。
- 确认文件已加到 target 的 “Copy Bundle Resources” 里(不是 “Compile Sources”)
- 调试时先打印
Bundle.main.resourcePath,再用FileManager.default.contentsOfDirectory(atPath:)看实际有哪些文件 - 如果 HTML 需要动态生成或修改,别硬塞 bundle,改用
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first存到沙盒










