Odczytywanie zawartości HTML z UIWebView

132

Czy można odczytać surową zawartość HTML strony internetowej, która została załadowana do pliku UIWebView?

Jeśli nie, czy istnieje inny sposób pobierania surowej zawartości HTML ze strony internetowej w zestawie iPhone SDK (na przykład odpowiednik platformy .NET WebClient::openRead)?

Fuzzy Purple Monkey
źródło

Odpowiedzi:

216

Właściwie łatwiej odpowiedzieć na drugie pytanie. Spójrz na stringWithContentsOfURL:encoding:error:metodę NSString - umożliwia ona przekazanie adresu URL jako instancji NSURL (która może być łatwo utworzona z NSString) i zwraca ciąg z pełną zawartością strony pod tym adresem URL. Na przykład:

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

Po uruchomieniu ten kod googlePagebędzie zawierał kod HTML witryny www.google.com oraz errorwszelkie błędy napotkane podczas pobierania. (Powinieneś sprawdzić zawartość errorpo pobraniu.)

Przejście w drugą stronę (z UIWebView) jest nieco trudniejsze, ale zasadniczo jest to ta sama koncepcja. Będziesz musiał wyciągnąć żądanie z widoku, a następnie wykonać pobieranie jak wcześniej:

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

EDYCJA: Obie te metody mają jednak wpływ na wydajność, ponieważ wykonują żądanie dwukrotnie. Możesz obejść ten problem, pobierając zawartość z aktualnie załadowanego UIWebView za pomocą jego stringByEvaluatingJavascriptFromString:metody, takiej jak:

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

Spowoduje to pobranie bieżącej zawartości HTML widoku za pomocą modelu obiektu dokumentu, przeanalizuje JavaScript, a następnie przekaże ją jako NSString * HTML.

Innym sposobem jest najpierw wykonanie żądania programowo, a następnie załadowanie UIWebView z tego, o co prosiłeś. Powiedzmy, że weźmiesz drugi przykład powyżej, w którym masz NSString *pagewynik połączenia z stringWithContentsOfURL:encoding:error:. Następnie możesz wypchnąć ten ciąg do widoku internetowego za pomocą loadHTMLString:baseURL:, zakładając, że trzymałeś się również żądanego NSURL:

[yourWebView loadHTMLString:page baseURL:requestURL];

Nie jestem jednak pewien, czy uruchomi to JavaScript znaleziony na ładowanej stronie (nazwa metody,, loadHTMLStringjest nieco niejednoznaczna, a dokumentacja nie mówi o tym zbyt wiele).

Po więcej informacji:

Tim
źródło
1
Niesamowite! Dzięki za świetną odpowiedź. Zakładam, że obie metody powodują dwukrotne załadowanie strony, co może mieć wpływ na wydajność. Czy jest sposób, aby tego uniknąć?
Fuzzy Purple Monkey,
2
Właściwie są :) Odpowiedź zredagowana.
Tim
1
Tak, [yourWebView loadHTMLString: page baseURL: requestURL]; uruchomi JavaScript na stronie. Użyłem tego interfejsu API z mapami Google.
jeff7091
3
NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];kilkakrotnie uratował mi życie. Wydaje się, że w miarę możliwości powraca z dokumentu.
ennalax
2
@Hanuman To może ci pomóc: NSString * head = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.head.innerHTML"]; NSString * body = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.body.innerHTML"]; NSString * totalPage = dołącz oba ciągi.
Deepukjayan
91

jeśli chcesz wyodrębnić zawartość już załadowanego UIWebView, -stringByEvaluatingJavaScriptFromString. Na przykład:

NSString  *html = [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerHTML"];
Ben Gottlieb
źródło
10
Cholera, to sprytne!
jemmons,
2
Mam pytanie, co się stanie, jeśli zawartość będzie ciągiem JSON lub nawet nieprzetworzonym ciągiem bez tagu body?
stephenmuss
To nie jest zdrowe rozwiązanie! Cały kod javascript i informacje nagłówka zostaną w ten sposób utracone.
Radu Simionescu
43

Aby uzyskać całe nieprzetworzone dane HTML (z <head>i <body>):

NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];
tuoxie007
źródło
29

Należy zauważyć, że ciąg NSString stringWithContentsOfURL zgłosi zupełnie inny ciąg agenta użytkownika niż UIWebView wykonujący to samo żądanie. Więc jeśli twój serwer jest świadomy agenta użytkownika i odsyła inny kod HTML w zależności od tego, kto o to prosi, możesz w ten sposób nie uzyskać poprawnych wyników.

Zwróć również uwagę, że @"document.body.innerHTML"wspomniane powyżej wyświetli tylko to, co znajduje się w tagu body. Jeśli użyjesz @"document.all[0].innerHTML", otrzymasz zarówno głowę, jak i ciało. Co nadal nie jest pełną zawartością UIWebView, ponieważ nie odzyska on tagów! Doctype ani html, ale jest znacznie bliżej.

Pmatt
źródło
Teoretycznie można uzyskać typ dokumentu, żądając go od serwera. Jest prawdopodobne, że typ dokumentu nie zmieni się w zależności od useragent.
Moshe
20

Czytać:-

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

Modyfikować:-

html = [myWebView stringByEvaluatingJavaScriptFromString: @"document.getElementById('your div id').textContent=''"];
Agni
źródło
2

W Swift v3:

let doc = webView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")
Mc.Lover
źródło
1

Używam szybkiego rozszerzenia, takiego jak to:

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

}
Nathan
źródło
1

powinieneś spróbować tego:

document.documentElement.outerHTML
schumyxp
źródło
1

UIWebView

pobierz HTML z UIWebView`

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

ustaw HTML w 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
}

[pobierz / ustaw kod HTML z WKWebView]

yoAlex5
źródło