Lesen von HTML-Inhalten aus einer UIWebView

132

Ist es möglich, den rohen HTML-Inhalt einer Webseite zu lesen, die in eine geladen wurde UIWebView?

Wenn nicht, gibt es eine andere Möglichkeit, HTML-Rohinhalte von einer Webseite im iPhone SDK abzurufen (z. B. ein Äquivalent zu .NET WebClient::openRead)?

Fuzzy Purple Monkey
quelle

Antworten:

216

Die zweite Frage ist tatsächlich leichter zu beantworten. Schauen Sie sich die stringWithContentsOfURL:encoding:error:Methode von NSString an - Sie können eine URL als Instanz von NSURL übergeben (die leicht über NSString instanziiert werden kann) und eine Zeichenfolge mit dem vollständigen Inhalt der Seite unter dieser URL zurückgeben. Beispielsweise:

NSString *googleString = @"http://www.google.com";
NSURL *googleURL = [NSURL URLWithString:googleString];
NSError *error;
NSString *googlePage = [NSString stringWithContentsOfURL:googleURL 
                                                encoding:NSASCIIStringEncoding
                                                   error:&error];

googlePageEnthält nach dem Ausführen dieses Codes den HTML- Code für www.google.com sowie erroralle beim Abrufen aufgetretenen Fehler. (Sie sollten den Inhalt errornach dem Abrufen überprüfen .)

Der andere Weg (von einer UIWebView aus) ist etwas schwieriger, aber im Grunde das gleiche Konzept. Sie müssen die Anforderung aus der Ansicht abrufen und dann wie zuvor abrufen:

NSURL *requestURL = [[yourWebView request] URL];
NSError *error;
NSString *page = [NSString stringWithContentsOfURL:requestURL 
                                          encoding:NSASCIIStringEncoding
                                             error:&error];

BEARBEITEN: Beide Methoden haben jedoch einen Leistungseinbruch, da sie die Anforderung zweimal ausführen. Sie können dies umgehen, indem Sie den Inhalt aus einer aktuell geladenen UIWebView mithilfe der folgenden stringByEvaluatingJavascriptFromString:Methode abrufen :

NSString *html = [yourWebView stringByEvaluatingJavaScriptFromString: 
                                         @"document.body.innerHTML"];

Dadurch wird der aktuelle HTML-Inhalt der Ansicht mithilfe des Dokumentobjektmodells abgerufen, das JavaScript analysiert und als NSString * von HTML angezeigt.

Eine andere Möglichkeit besteht darin, Ihre Anfrage zuerst programmgesteuert zu bearbeiten und dann die UIWebView von der von Ihnen angeforderten zu laden. Nehmen wir an, Sie nehmen das zweite Beispiel oben, in dem Sie NSString *pageals Ergebnis eines Anrufs bei haben stringWithContentsOfURL:encoding:error:. Sie können diese Zeichenfolge dann mithilfe loadHTMLString:baseURL:von in die Webansicht verschieben, vorausgesetzt, Sie haben auch an der von Ihnen angeforderten NSURL festgehalten:

[yourWebView loadHTMLString:page baseURL:requestURL];

Ich bin mir jedoch nicht sicher, ob hier JavaScript ausgeführt wird, das auf der von Ihnen geladenen Seite gefunden wurde (der Methodenname loadHTMLStringist etwas mehrdeutig, und die Dokumente sagen nicht viel darüber aus).

Für mehr Information:

Tim
quelle
1
Genial! Danke für die tolle Antwort. Ich gehe davon aus, dass beide Methoden dazu führen, dass die Seite zweimal geladen wird, was sich auf die Leistung auswirken kann. Gibt es eine Möglichkeit, dies zu vermeiden?
Fuzzy Purple Monkey
2
In der Tat gibt es :) Bearbeitete Antwort.
Tim
1
Ja, [yourWebView loadHTMLString: page baseURL: requestURL]; führt das Javascript auf der Seite aus. Ich habe diese API mit Google Maps verwendet.
Jeff7091
3
NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];war schon mehrmals ein Lebensretter für mich. Es scheint so weit wie möglich aus dem Dokument zurückzukehren.
Ennalax
2
@Hanuman Dies könnte Ihnen helfen: NSString * head = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.head.innerHTML"]; NSString * body = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.body.innerHTML"]; NSString * totalPage = beide Zeichenfolgen anhängen.
Deepukjayan
91

Wenn Sie den Inhalt einer bereits geladenen UIWebView extrahieren möchten, verwenden Sie -stringByEvaluatingJavaScriptFromString. Beispielsweise:

NSString  *html = [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerHTML"];
Ben Gottlieb
quelle
10
Verdammt, das ist klug!
Jemmons
2
Die Frage, die ich habe, ist, was passiert, wenn der Inhalt eine JSON-Zeichenfolge oder sogar eine Rohzeichenfolge ohne Body-Tag ist?
Stephenmuss
Dies ist keine gesunde Lösung! Der gesamte Javascript-Code und die Header-Informationen gehen auf diese Weise verloren.
Radu Simionescu
43

So erhalten Sie die gesamten HTML-Rohdaten (mit <head>und <body>):

NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];
tuoxie007
quelle
29

Beachten Sie, dass der NSString stringWithContentsOfURL eine völlig andere Benutzeragentenzeichenfolge meldet als der UIWebView, der dieselbe Anforderung stellt. Wenn Ihr Server also User-Agent-fähig ist und je nachdem, wer danach fragt, unterschiedliche HTML-Dateien zurücksendet, erhalten Sie auf diese Weise möglicherweise keine korrekten Ergebnisse.

Beachten Sie auch, dass @"document.body.innerHTML"oben nur das angezeigt wird, was sich im Body-Tag befindet. Wenn Sie verwenden, erhalten @"document.all[0].innerHTML"Sie sowohl Kopf als auch Körper. Dies ist immer noch nicht der vollständige Inhalt von UIWebView, da die Tags! Doctype oder html nicht zurückgegeben werden, aber es ist viel näher.

Pmatt
quelle
Theoretisch könnten Sie den Doctype erhalten, indem Sie ihn vom Server anfordern. Es ist wahrscheinlich, dass sich der Doctype basierend auf Useragent nicht ändert.
Moshe
20

Lesen:-

NSString *html = [myWebView stringByEvaluatingJavaScriptFromString: @"document.getElementById('your div id').textContent"];
NSLog(html);    

Ändern:-

html = [myWebView stringByEvaluatingJavaScriptFromString: @"document.getElementById('your div id').textContent=''"];
Agni
quelle
2

In Swift v3:

let doc = webView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")
Mc.Lover
quelle
1

Ich benutze eine schnelle Erweiterung wie diese:

extension UIWebView {
    var htmlContent:String? {
        return self.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")
    }

}
Nathan
quelle
1

Sie sollten dies versuchen:

document.documentElement.outerHTML
schumyxp
quelle
1

UIWebView

Holen Sie sich HTML von UIWebView`

let content = uiWebView.stringByEvaluatingJavaScript(from: "document.body.innerHTML")

Setzen Sie HTML in UIWebView

//Do not forget to extend a class from `UIWebViewDelegate` and nil the delegate

func someFunction() {

    let uiWebView = UIWebView()
    uiWebView.loadHTMLString("<html><body></body></html>", baseURL: nil)
    uiWebView.delegate = self as? UIWebViewDelegate
}

func webViewDidFinishLoad(_ webView: UIWebView) {
    //ready to be processed
}

[HTML von WKWebView abrufen / festlegen]

yoAlex5
quelle