Чтение HTML-содержимого из UIWebView


132

Можно ли прочитать необработанное HTML-содержимое веб-страницы, загруженной в UIWebView?

Если нет, есть ли другой способ извлечь необработанный HTML-контент с веб-страницы в iPhone SDK (например, эквивалент .NET WebClient::openRead)?

Ответы:


216

На второй вопрос на самом деле ответить легче. Посмотрите на stringWithContentsOfURL:encoding:error:метод NSString - он позволяет вам передать URL-адрес в качестве экземпляра NSURL (который может быть легко создан из NSString) и возвращает строку с полным содержимым страницы по этому URL-адресу. Например:

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

После выполнения этого кода он googlePageбудет содержать HTML для www.google.com и errorвсе ошибки, обнаруженные при выборке. (Вы должны проверить содержимое errorпосле получения.)

Обратный путь (из UIWebView) немного сложнее, но в основном это та же концепция. Вам нужно будет вытащить запрос из представления, а затем выполнить выборку, как раньше:

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

РЕДАКТИРОВАТЬ: оба эти метода снижают производительность, поскольку они выполняют запрос дважды. Вы можете обойти это, захватив контент из загруженного в данный момент UIWebView, используя его stringByEvaluatingJavascriptFromString:метод, как таковой:

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

Это захватит текущее HTML-содержимое представления с помощью объектной модели документа, проанализирует JavaScript, а затем передаст его вам как NSString * HTML.

Другой способ - сначала выполнить ваш запрос программно, а затем загрузить UIWebView из того, что вы запросили. Допустим, вы взяли второй пример выше, где NSString *pageв результате вызова stringWithContentsOfURL:encoding:error:. Затем вы можете вставить эту строку в веб-представление, используя loadHTMLString:baseURL:, при условии, что вы также сохранили запрашиваемый вами NSURL:

[yourWebView loadHTMLString:page baseURL:requestURL];

Однако я не уверен, запустится ли при этом JavaScript, найденный на загружаемой вами странице (имя метода loadHTMLString, несколько двусмысленно, и в документации об этом мало говорится).

Для получения дополнительной информации:


1
Потрясающие! Спасибо за отличный ответ. Я предполагаю, что оба метода приводят к двойной загрузке страницы, что может повлиять на производительность. Есть ли способ избежать этого?
Fuzzy Purple Monkey

2
Собственно есть :) Отредактированный ответ.
Тим

1
Да, [yourWebView loadHTMLString: page baseURL: requestURL]; запустит Javascript на странице. Я использовал этот API с картами Google.
jeff7091

3
NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];уже несколько раз был для меня палочкой-выручалочкой. Вроде как можно больше вернуть из документа.
ennalax

2
@Hanuman Это может вам помочь: NSString * head = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.head.innerHTML"]; NSString * body = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.body.innerHTML"]; NSString * totalPage = добавить обе строки.
Deepukjayan

91

если вы хотите извлечь содержимое уже загруженного UIWebView, -stringByEvaluatingJavaScriptFromString. Например:

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

10
Блин, это умно!
jemmons

2
У меня возникает вопрос: что произойдет, если содержимое окажется строкой JSON или даже необработанной строкой без тега тела?
stephenmuss

Это не здоровое решение! Таким образом теряется весь код javascript и информация заголовка.
Radu Simionescu

43

Чтобы получить все необработанные данные HTML (с помощью <head>и <body>):

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

29

Обратите внимание, что NSString stringWithContentsOfURL сообщит о совершенно другой строке пользовательского агента, чем UIWebView, выполняющий тот же запрос. Поэтому, если ваш сервер осведомлен о пользовательском агенте и отправляет обратно разные html в зависимости от того, кто его запрашивает, вы можете не получить правильные результаты таким образом.

Также обратите внимание, что @"document.body.innerHTML"упомянутое выше будет отображать только то, что находится в теге body. При использовании @"document.all[0].innerHTML"вы получите и голову, и тело. Это все еще не полное содержимое UIWebView, поскольку он не вернет теги! Doctype или html, но это намного ближе.


Теоретически вы можете получить doctype, запросив его с сервера. Вероятно, что тип документа не изменится в зависимости от агента-пользователя.
Моше

20

Читать:-

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

Модифицировать:-

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

2

В Swift v3:

let doc = webView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")


1

Я использую быстрое расширение вроде этого:

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

}


1

UIWebView

получить HTML из UIWebView`

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

установить HTML в 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 из WKWebView]

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.