I am trying to load a transit website so I can scrape the stop times for a given stop. After I load the url, the stop times are loaded in a bit later dynamically through javascript. My goal is to detect the presence of elements with a class of "stop-time". If these elements are present in the html I can then parse the html. But before I can parse the html I have to wait for these elements with class of "stop-time" to appear. I read through a bunch of other SO questions but I couldn't quite piece it together. I am implementing the didReceive message function but I'm not really sure how to load in the javascript I need to detect the presence of the elements (elements with class of "stop-time"). I successfully injected some javascript to prevent the location permission popup from showing.
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
}
}
To check if your WKWebView has loaded easily implement the following method: import WebKit import UIKit class ViewController: UIViewController, WKNavigationDelegate { let webView = WKWebView() func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
WKWebView replaces the UIWebView class in iOS 8 and later, and it replaces the WebView class in macOS 10.10 and later. Embed a WKWebView object programmatically into your view hierarchy, or add it using Interface Builder.
WebView can be defined as an object which can display the interactive web content and load HTML strings within the iOS application for an in-app browser. It is an instance of the WKWebView class, which inherits the UIView class.
First of all You need to inject next script to detect appearence of elements via mutations observer:
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 });
Then You need to subscribe for event 'stopTimesLoaded':
contentController.add(self, name: "stopTimesLoaded")
And finally add code to process data in
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With