如何在WKWebView加载网站后检测元素何时可见?

10

我正在尝试加载一家公交网站,以便可以爬取给定车站的停靠时间。当我加载URL时,停靠时间稍后通过javascript动态加载。我的目标是检测HTML中是否存在带有"stop-time"类名的元素。如果这些元素存在于HTML中,我就可以解析HTML。但在解析HTML之前,我必须等待具有"stop-time"类名的元素出现。我已经阅读了许多其他SO问题,但我无法完全理解它们。我正在实现didReceive消息函数,但我不确定如何加载所需的javascript以检测元素(具有"stop-time"类名的元素)。我成功注入了一些javascript来防止位置权限弹出窗口的显示。

override func viewDidLoad() {
    super.viewDidLoad()

    let contentController = WKUserContentController()
    let scriptSource = "navigator.geolocation.getCurrentPosition = function(success, error, options) {}; navigator.geolocation.watchPosition = function(success, error, options) {}; navigator.geolocation.clearWatch = function(id) {};"
    let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentStart, forMainFrameOnly: true)
    contentController.addUserScript(script)

    let config = WKWebViewConfiguration()
    config.userContentController = contentController

    webView = WKWebView(frame: .zero, configuration: config)
    self.view = self.webView!

    loadStopTimes("https://www.website.com/stop/1000")
}

func loadStopTimes(_ busUrl: String) {
    let urlString = busUrl
    let url = URL(string: urlString)!
    let urlRequest = URLRequest(url: url)
    webView?.load(urlRequest)
}

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if(message.name == "stopTimesLoaded") {
        // stop times now present so take the html and parse the stop times
    }
}

如果“stop-time”元素加载了脚本,您可以在加载完成后从JavaScript中调用您的应用程序中的方法。https://dev59.com/UWkw5IYBdhLWcg3wirCs - ymutlu
1个回答

3

首先,您需要注入下一个脚本,以通过变异观察器检测元素的出现:

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      console.log('mutation.type = ' + mutation.type);
      for (var i = 0; i < mutation.addedNodes.length; i++) {
        var node = mutation.addedNodes[i];
        if (node.nodeType == Node.ELEMENT_NODE && node.className == 'stop-time') {
            var content = node.textContent;
            console.log('  "' + content + '" added');
            window.webkit.messageHandlers.stopTimesLoaded.postMessage({ data: content });
        }
      }
    });
  });
observer.observe(document, { childList: true, subtree: true });

那么您需要订阅事件 'stopTimesLoaded':
contentController.add(self, name: "stopTimesLoaded")

最后,添加代码来处理数据。
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)

我现在正在尝试检测具有类“stoproutes-results”的容器的存在。我尝试将node.className == 'stop-time'更改为node.className == 'stoproutes-results',但它不起作用。有任何想法为什么? - user3614030
您确定已经为在内容控制器中注册的消息处理程序更改了吗? window.webkit.messageHandlers 只能通过 contentController.add 注册的事件发送消息。 - HereTrix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接