Lire du contenu HTML à partir d'une UIWebView

132

Est-il possible de lire le contenu HTML brut d'une page Web qui a été chargée dans un UIWebView?

Sinon, existe-t-il un autre moyen d'extraire du contenu HTML brut d'une page Web dans le SDK iPhone (tel qu'un équivalent du .NET WebClient::openRead)?

Singe violet flou
la source

Réponses:

216

La deuxième question est en fait plus facile à répondre. Regardez la stringWithContentsOfURL:encoding:error:méthode de NSString - elle vous permet de passer une URL en tant qu'instance de NSURL (qui peut facilement être instanciée à partir de NSString) et renvoie une chaîne avec le contenu complet de la page à cette URL. Par exemple:

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

Après avoir exécuté ce code, googlePagecontiendra le code HTML de www.google.com et errorcontiendra toutes les erreurs rencontrées lors de la récupération. (Vous devriez vérifier le contenu de erroraprès la récupération.)

Aller dans l'autre sens (à partir d'un UIWebView) est un peu plus délicat, mais c'est fondamentalement le même concept. Vous devrez extraire la requête de la vue, puis effectuer la récupération comme avant:

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

EDIT: Ces deux méthodes ont un impact négatif sur les performances, car elles font la demande deux fois. Vous pouvez contourner ce problème en récupérant le contenu d'une UIWebView actuellement chargée à l'aide de sa stringByEvaluatingJavascriptFromString:méthode, en tant que telle:

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

Cela récupérera le contenu HTML actuel de la vue en utilisant le modèle d'objet de document, analysera le JavaScript, puis vous le donnera sous forme de NSString * de HTML.

Une autre méthode consiste à effectuer d'abord votre demande par programme, puis à charger l'UIWebView à partir de ce que vous avez demandé. Disons que vous prenez le deuxième exemple ci-dessus, où vous avez NSString *pageà la suite d'un appel à stringWithContentsOfURL:encoding:error:. Vous pouvez ensuite pousser cette chaîne dans la vue Web en utilisant loadHTMLString:baseURL:, en supposant que vous ayez également conservé la NSURL que vous avez demandée:

[yourWebView loadHTMLString:page baseURL:requestURL];

Je ne suis pas sûr, cependant, si cela exécutera JavaScript trouvé dans la page que vous chargez (le nom de la méthode,, loadHTMLStringest quelque peu ambigu, et les documents n'en disent pas grand chose).

Pour plus d'informations:

Tim
la source
1
Impressionnant! Merci pour la bonne réponse. Je suppose que les deux méthodes entraînent le chargement de la page deux fois, ce qui peut avoir un impact sur les performances. Y a-t-il un moyen d'éviter cela?
Fuzzy Purple Monkey le
2
En fait, il y a :) Réponse éditée.
Tim
1
Oui, [yourWebView loadHTMLString: page baseURL: requestURL]; exécutera le Javascript dans la page. J'ai utilisé cette API avec Google Maps.
jeff7091
3
NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];a été une bouée de sauvetage pour moi à plusieurs reprises maintenant. Il semble revenir du document autant que possible.
ennalax
2
@Hanuman Cela peut vous aider: NSString * head = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.head.innerHTML"]; NSString * body = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.body.innerHTML"]; NSString * totalPage = ajouter les deux chaînes.
Deepukjayan
91

si vous souhaitez extraire le contenu d'un UIWebView déjà chargé, -stringByEvaluatingJavaScriptFromString. Par exemple:

NSString  *html = [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerHTML"];
Ben Gottlieb
la source
10
Merde, c'est malin!
jemmons
2
La question que je me pose est ce qui se passe si le contenu se trouve être une chaîne JSON ou même une chaîne brute sans balise body?
stephenmuss
Ce n'est pas une solution saine! Tout le code javascript et les informations d'en-tête sont perdus de cette façon.
Radu Simionescu
43

Pour obtenir toutes les données brutes HTML (avec <head>et <body>):

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

Notez que la chaîne NSString stringWithContentsOfURL signalera une chaîne user-agent totalement différente de celle de UIWebView effectuant la même demande. Donc, si votre serveur est conscient de l'agent utilisateur et renvoie un code HTML différent en fonction de la personne qui le demande, vous risquez de ne pas obtenir de résultats corrects de cette façon.

Notez également que ce qui @"document.body.innerHTML"précède n'affichera que ce qui est dans la balise body. Si vous utilisez, @"document.all[0].innerHTML"vous obtiendrez à la fois la tête et le corps. Ce qui n'est toujours pas le contenu complet de l'UIWebView, car il ne récupérera pas les balises! Doctype ou html, mais c'est beaucoup plus proche.

Pmatt
la source
Théoriquement, vous pouvez obtenir le doctype en le demandant au serveur. Il est probable que le doctype ne changera pas en fonction de useragent.
Moshe
20

Lire:-

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

Modifier:-

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

Dans Swift v3:

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

J'utilise une extension rapide comme celle-ci:

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

}
Nathan
la source
1

vous devriez essayer ceci:

document.documentElement.outerHTML
schumyxp
la source
1

UIWebView

obtenir du HTML depuis UIWebView`

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

définir HTML dans 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
}

[obtenir / définir le HTML à partir de WKWebView]

yoAlex5
la source