我一直在尝试从具有动态/延迟加载的网站加载 HTML。到目前为止,我见过的唯一可行的解决方案是使用 WebView,然后在调用
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0)
方法之前使用延迟 (evaluateJavaScript
)。见下图:
import SwiftSoup
import WebKit
private let myWebView: WKWebView = {
let prefs = WKPreferences()
let config = WKWebViewConfiguration()
config.preferences = prefs
let webView = WKWebView(frame: .zero, configuration: config)
return webView
}()
var allProducts: [Element] = []
override func viewDidLoad() {
super.viewDidLoad()
myWebView.navigationDelegate = self
let myURL = URL(string: "https://shop.coles.com.au/a/national/specials/search/coles-weekly-specials?pageNumber=1")
myWebView.load(URLRequest(url: myURL!))
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
myWebView.evaluateJavaScript("document.body.innerHTML") { [self] result, error in
guard let htmlContent = result, error == nil else {
print("error")
return
}
do {
let doc = try SwiftSoup.parse(htmlContent as! String)
allProducts = try doc.select("header").array()
} catch {
print("error")
}
}
}
}
这样做的问题是,固定延迟非常危险/效率低下,因为它可能无法加载所有数据,或者可能会浪费时间。我想在代码上实现一个 while 循环,以便它重复求值,直到找到数据(见下文):
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
while allProducts.count < 1 {
myWebView.evaluateJavaScript("document.body.innerHTML") { [self] result, error in
guard let htmlContent = result, error == nil else {
print("error")
return
}
do {
let doc = try SwiftSoup.parse(htmlContent as! String)
allProducts = try doc.select("header").array()
} catch {
print("error")
}
}
}
}
但是当我运行这个时,控制台的响应非常出乎意料,我认为它甚至没有运行过一次评估代码。我假设您不能在特定负载上多次调用
evaluateJavaScript
方法。
有谁知道这段代码的任何解决方法,或者任何其他方式来加载动态加载的 HTML。任何帮助将不胜感激!!!!
我遇到了这个问题,你解决了吗?