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

基于WKWebKit实现网页抓取自动化的问题求助

解决WKWebKit多步骤JS自动执行的问题

我之前也碰到过类似的WKWebKit多步骤操作难题,给你几个亲测有效的解决方案,帮你实现第一步完成后自动触发下一步:

1. 用evaluateJavaScript的完成回调嵌套执行

WKWebKit确实没有直接的onComplete函数,但每一次调用evaluateJavaScript都可以通过它的completionHandler来确认这一步JS是否执行完毕,然后在这个回调里启动下一步操作。这种方式适合步骤较少的场景,逻辑清晰直接:

// 先执行第一步JS
webView.evaluateJavaScript("document.querySelector('#first-button').click();") { (result, error) in
    if let error = error {
        print("第一步执行出错: \(error.localizedDescription)")
        return
    }
    // 第一步成功完成,立刻执行第二步JS
    webView.evaluateJavaScript("document.querySelector('#second-form').submit();") { (result, error) in
        if let error = error {
            print("第二步执行出错: \(error.localizedDescription)")
        }
        // 后续步骤可以继续嵌套
    }
}

2. 监听网页自定义事件,实现Native与JS的联动

如果你的操作涉及页面DOM变化(比如点击按钮后页面加载新内容、渲染新元素),单纯靠回调嵌套可能不够精准。这时候可以让网页(或者你注入的JS)在步骤完成时发送一个自定义事件,Native端监听这个事件后再执行下一步:

第一步:在JS中发送自定义事件

你可以把这段JS作为第一步操作的一部分,或者注入到页面中:

// 第一步操作完成后,触发自定义事件
document.querySelector('#first-button').addEventListener('click', function() {
    // 这里是按钮点击后的逻辑,完成后发送事件
    document.dispatchEvent(new CustomEvent('step1Done'));
});

第二步:Native端监听事件

实现WKScriptMessageHandler来接收事件通知,然后执行下一步:

class StepHandler: NSObject, WKScriptMessageHandler {
    weak var webView: WKWebView?
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "step1Done" {
            // 收到第一步完成的信号,执行第二步
            webView?.evaluateJavaScript("document.querySelector('#second-form').submit();", completionHandler: nil)
        }
    }
}

// 初始化WebView时注册处理器
let stepHandler = StepHandler()
stepHandler.webView = webView
webView.configuration.userContentController.add(stepHandler, name: "step1Done")

3. 封装执行队列,管理多步骤操作

如果你的操作步骤很多,嵌套回调会显得代码臃肿,这时候可以封装一个简单的队列类,自动按顺序执行每一步JS,前一步完成后自动启动下一步:

class JSActionQueue {
    private let webView: WKWebView
    private var actionQueue: [String] = []
    private var isRunning = false
    
    init(webView: WKWebView) {
        self.webView = webView
    }
    
    // 添加要执行的JS步骤
    func enqueueJS(_ js: String) {
        actionQueue.append(js)
        if !isRunning {
            startNextAction()
        }
    }
    
    private func startNextAction() {
        guard let nextJS = actionQueue.first else {
            isRunning = false
            return
        }
        isRunning = true
        webView.evaluateJavaScript(nextJS) { [weak self] (_, error) in
            if let error = error {
                print("执行步骤失败: \(error.localizedDescription)")
            }
            // 移除已完成的步骤,执行下一个
            self?.actionQueue.removeFirst()
            self?.startNextAction()
        }
    }
}

// 使用方式:初始化队列,添加所有步骤
let jsQueue = JSActionQueue(webView: webView)
jsQueue.enqueueJS("document.querySelector('#first-button').click();")
jsQueue.enqueueJS("document.querySelector('#second-form').submit();")
jsQueue.enqueueJS("document.querySelector('#final-button').click();")

额外注意点

  • 确保所有JS操作都在页面加载完成后启动,你可以在WKNavigationDelegate的webView(_:didFinish:)回调里初始化队列或者执行第一步操作。
  • 如果某一步涉及页面跳转,要等待didFinish回调确认新页面加载完成后,再执行下一步JS,避免出现找不到DOM元素的问题。

内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:37:15