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

URLSession请求动态网页未加载内容:如何等待脚本执行?

解决动态渲染页面的HTML获取问题

你遇到的问题很典型:URLSession只会获取服务器返回的初始静态HTML,而页面里的实际内容是通过客户端JavaScript动态加载渲染的,所以你拿到的只是页面加载前的loading占位元素,而非最终渲染后的内容。下面给你两种可行的解决方案:

方法一:使用WKWebView渲染页面后获取内容

WKWebView是iOS/macOS上的webkit内核组件,它会像浏览器一样执行页面的JavaScript脚本,等待页面完全渲染后再提取HTML。示例代码如下:

import WebKit

class ViewController: UIViewController, WKNavigationDelegate {
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 配置WKWebView
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.navigationDelegate = self
        view.addSubview(webView)
        
        // 设置约束(如果需要)
        webView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            webView.topAnchor.constraint(equalTo: view.topAnchor),
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        // 加载目标URL
        guard let url = URL(string: "https://www.ultimatetennisstatistics.com/playerProfile?playerId=3333") else { return }
        webView.load(URLRequest(url: url))
    }

    // 页面加载完成后的回调
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 执行JS获取渲染后的完整HTML
        webView.evaluateJavaScript("document.documentElement.outerHTML") { (result, error) in
            if let htmlString = result as? String {
                // 这里可以处理渲染后的HTML,查找class为"row"的div
                print(htmlString)
            } else if let error = error {
                print("获取HTML失败:\(error.localizedDescription)")
            }
        }
    }

    // 处理加载失败的情况
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print("页面加载失败:\(error.localizedDescription)")
    }
}

这种方法的优势是完全模拟浏览器行为,能处理所有JS渲染的内容;缺点是需要依赖WebView组件,性能比直接请求API稍差,且在后台线程/非UI环境下使用会有局限。

方法二:直接调用网站的API接口

很多动态渲染的网站会通过AJAX/Fetch请求后端API获取数据,再在前端渲染。你可以通过Chrome开发者工具的Network面板(切换到XHR/Fetch标签),查找页面加载过程中请求的API接口,直接请求这些接口获取结构化的JSON数据,这比解析HTML更高效。

比如,你打开目标页面后,查看Network请求,可能会找到类似/api/player/3333或者/playerStats?playerId=3333的接口,直接用URLSession请求这个接口,就能拿到你需要的统计数据,无需处理HTML解析。

示例代码(假设找到的API接口是https://www.ultimatetennisstatistics.com/api/playerProfile?playerId=3333):

guard let apiUrl = URL(string: "https://www.ultimatetennisstatistics.com/api/playerProfile?playerId=3333") else { return }

let task = URLSession.shared.dataTask(with: apiUrl) { (data, response, error) in
    if let error = error {
        print("请求失败:\(error.localizedDescription)")
        return
    }
    
    guard let data = data else {
        print("无返回数据")
        return
    }
    
    do {
        // 解析JSON数据,根据API返回的结构定义对应的Model
        let playerData = try JSONSerialization.jsonObject(with: data, options: [])
        print(playerData)
        // 这里可以直接提取需要的统计字段,无需处理HTML
    } catch {
        print("JSON解析失败:\(error.localizedDescription)")
    }
}
task.resume()

这种方法的优势是性能更高,数据结构更清晰;缺点是需要分析网站的API接口,部分网站可能会有签名或反爬机制,需要额外处理。

内容的提问来源于stack exchange,提问作者Hergen Lehmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:23:14