Get HTML from WKWebview in Swift

SwiftWkwebview

Swift Problem Overview


I log into a website using WKWebView and now i would like to parse the html of the website. How can I access the websites html in swift? I know how it works for a UIWebView but not for WKWebView.

Thanks for your help!

Swift Solutions


Solution 1 - Swift

If you wait until the page has loaded you can use:

webView.evaluateJavaScript("document.documentElement.outerHTML.toString()", 
                           completionHandler: { (html: Any?, error: Error?) in
    print(html)
})

You could also inject some javascript that returns you back the HTML.

let script = WKUserScript(source: javascriptString, injectionTime: injectionTime, forMainFrameOnly: true)
userContentController.addUserScript(script)
self.webView.configuration.userContentController.addScriptMessageHandler(self, name: "didGetHTML")



func userContentController(userContentController: WKUserContentController,
        didReceiveScriptMessage message: WKScriptMessage) {
     
        if message.name == "didGetHTML" {
            if let html = message.body as? String {
                print(html)
            }
        }
}

The javascript you could inject looks something like:

webkit.messageHandlers.didGetHTML.postMessage(document.documentElement.outerHTML.toString());

Solution 2 - Swift

WKWebView

get HTML from WKWebView

wkWebView.evaluateJavaScript("document.body.innerHTML", completionHandler: { (value: Any!, error: Error!) -> Void in
        
    if error != nil {
        //Error logic
        return
    }

    //let result = value as? String
    //Main logic
})

set HTML into WKWebView

//Do not forget to extend a class from `WKNavigationDelegate`

func someFunction() {
    let wkWebView = WKWebView()
    
    wkWebView.loadHTMLString("<html><body></body></html>", baseURL: nil)
    wkWebView.navigationDelegate = self as? WKNavigationDelegate
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    //ready to be processed
}

[get/set HTML from UIWebView]

Solution 3 - Swift

I was here to try to get clues about getting result after asking token form DROPBOX new APIS. (I am implementing their flow WITHOUT all the stuff of their SDK) Hope can help someone.

Now Dropbox uses a web page as login, and calls back YOUR url where You can process token.

import WebKit
import SwiftUI

// some code from:
// https://benoitpasquier.com/create-webview-in-swiftui/
// THX pasquier!

let APP_KEY = "YOUR APP KEY"
let REDIRECT_URI = "<YOUR SITE>.dropbox_auth.php"
let DB_URL = "https://www.dropbox.com/1/oauth2/authorize?client_id=APP_KEY&token_access_type=offline&response_type=code&redirect_uri=REDIRECT_URI"

class MyWKDelegate: NSObject, WKNavigationDelegate{
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("End loading")
        webView.evaluateJavaScript("document.body.innerHTML", completionHandler: { result, error in
            
            if let html = result as? String {
                    print(html)
                }
            })
    }
}

struct WebView: UIViewRepresentable {
        
    typealias UIViewType = WKWebView

    let webView: WKWebView
    
    func makeUIView(context: Context) -> WKWebView {
        return webView
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) { }
}


class WebViewModel: ObservableObject {
    let webView: WKWebView
    let url: URL!
    let delegate = MyWKDelegate()
    
    init() {
        webView = WKWebView(frame: .zero)
        webView.navigationDelegate = delegate

        let urlStr = DB_URL.replacingOccurrences(of: "APP_KEY", with: APP_KEY).replacingOccurrences(of: "REDIRECT_URI", with: REDIRECT_URI)
        print(urlStr)
        url = URL(string: urlStr)

        loadUrl()
    }
    
    func loadUrl() {
        webView.load(URLRequest(url: url))
    }
}

Solution 4 - Swift

Combining answers 1 and 3 did the trick for me:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
   print("End loading")        
   webView.evaluateJavaScript("document.documentElement.outerHTML", completionHandler: { result, error in         
      if let datHtml = result as? String {
         print(datHtml)
         // parse datHtml here
         }
      } )
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMotoxXView Question on Stackoverflow
Solution 1 - SwiftOnatoView Answer on Stackoverflow
Solution 2 - SwiftyoAlex5View Answer on Stackoverflow
Solution 3 - SwiftingcontiView Answer on Stackoverflow
Solution 4 - SwiftMarkv07View Answer on Stackoverflow