You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift如何解析经JavaScript更新DOM后的动态HTML页面内容?

问题解决方案

你当前使用的URLSession仅能获取服务器返回的原始静态HTML,SwiftSoup属于静态HTML解析库,不具备JavaScript执行能力,因此无法拿到JS动态渲染生成的DOM元素。要获取和浏览器审查元素一致的DOM内容,可采用以下方案:

方案1:使用WKWebView加载页面后提取DOM(iOS/macOS原生首选方案)

WKWebView是iOS/macOS内置的浏览器内核,支持完整的JS执行能力,你可以通过它加载页面,等待JS执行完成后再提取渲染后的完整HTML交给SwiftSoup解析。

import WebKit
import SwiftSoup

// 注意WKWebView需要在主线程初始化
class DOMFetcher: NSObject, WKNavigationDelegate {
    private var webView: WKWebView!
    private var completion: ((String?, Error?) -> Void)?
    
    override init() {
        super.init()
        let config = WKWebViewConfiguration()
        // 可选:禁用缓存保证拿到最新内容
        config.websiteDataStore = WKWebsiteDataStore.nonPersistent()
        webView = WKWebView(frame: .zero, configuration: config)
        webView.navigationDelegate = self
    }
    
    func fetchRenderedHTML(url: URL, completion: @escaping (String?, Error?) -> Void) {
        self.completion = completion
        DispatchQueue.main.async {
            let request = URLRequest(url: url)
            self.webView.load(request)
        }
    }
    
    // 页面加载完成回调
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 可选:如果页面有懒加载逻辑,可加延迟后再拿DOM,比如延迟1秒
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            // 执行JS获取完整HTML
            webView.evaluateJavaScript("document.documentElement.outerHTML") { [weak self] result, error in
                if let error = error {
                    self?.completion?(nil, error)
                    return
                }
                guard let html = result as? String else {
                    self?.completion?(nil, NSError(domain: "DOMFetcher", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法获取HTML内容"]))
                    return
                }
                self?.completion?(html, nil)
            }
        }
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        completion?(nil, error)
    }
}

// 使用示例
let fetcher = DOMFetcher()
guard let targetURL = URL(string: "你的目标链接") else { return }
fetcher.fetchRenderedHTML(url: targetURL) { html, error in
    if let error = error {
        print("获取失败: \(error.localizedDescription)")
        return
    }
    guard let renderedHTML = html else { return }
    do {
        let doc = try SwiftSoup.parse(renderedHTML)
        let elements = try doc.getAllElements().array()
        // 后续解析逻辑
    } catch {
        print("解析失败: \(error.localizedDescription)")
    }
}

方案2:直接抓取动态数据接口(高效优先方案)

大部分动态渲染的内容都是页面通过JS请求后端接口返回JSON数据后生成的,你可以通过浏览器开发者工具的「网络」面板抓包找到对应的数据接口,直接请求接口获取结构化的JSON数据,比解析DOM效率更高、稳定性更好。

注意事项

  • 部分网站会做反爬检测,需要给请求加上和浏览器一致的User-Agent、Cookie等头部信息,才能拿到正常的返回内容
  • 如果页面有滚动加载、点击加载等交互触发的内容,需要在WKWebView中通过执行对应的JS模拟交互后,再提取DOM

内容的提问来源于stack exchange,提问作者aadi sach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 12:36:02