Lectura de contenido HTML desde un UIWebView

132

¿Es posible leer el contenido HTML sin formato de una página web que se ha cargado en un UIWebView?

Si no, ¿hay otra forma de extraer contenido HTML sin formato de una página web en el SDK de iPhone (como un equivalente de .NET WebClient::openRead)?

Mono púrpura difuso
fuente

Respuestas:

216

La segunda pregunta es realmente más fácil de responder. Mire el stringWithContentsOfURL:encoding:error:método de NSString: le permite pasar una URL como una instancia de NSURL (que se puede instanciar fácilmente desde NSString) y devuelve una cadena con el contenido completo de la página en esa URL. Por ejemplo:

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

Después de ejecutar este código, googlePagecontendrá el HTML para www.google.com y errorcontendrá los errores encontrados en la búsqueda. (Debe verificar el contenido de errordespués de la búsqueda).

Ir hacia el otro lado (desde un UIWebView) es un poco más complicado, pero es básicamente el mismo concepto. Tendrá que extraer la solicitud de la vista, luego realizar la búsqueda como antes:

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

EDITAR: Sin embargo, ambos métodos tienen un impacto en el rendimiento, ya que hacen la solicitud dos veces. Puede solucionar esto agarrando el contenido de un UIWebView cargado actualmente utilizando su stringByEvaluatingJavascriptFromString:método, como tal:

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

Esto tomará el contenido HTML actual de la vista usando el Modelo de Objeto del Documento, analizará el JavaScript y luego se lo dará como un NSString * de HTML.

Otra forma es hacer su solicitud mediante programación primero, luego cargue el UIWebView de lo que solicitó. Supongamos que toma el segundo ejemplo anterior, donde tiene NSString *pagecomo resultado una llamada a stringWithContentsOfURL:encoding:error:. Luego puede insertar esa cadena en la vista web utilizando loadHTMLString:baseURL:, suponiendo que también haya mantenido el NSURL que solicitó:

[yourWebView loadHTMLString:page baseURL:requestURL];

Sin embargo, no estoy seguro de si esto ejecutará JavaScript encontrado en la página que carga (el nombre del método loadHTMLStringes algo ambiguo y los documentos no dicen mucho al respecto).

Para más información:

Tim
fuente
1
¡Increíble! Gracias por la gran respuesta. Supongo que ambos métodos hacen que la página se cargue dos veces, lo que puede tener un impacto en el rendimiento. ¿Hay alguna manera de evitar eso?
Fuzzy Purple Monkey
2
De hecho, hay :) Respuesta editada.
Tim
1
Sí, [yourWebView loadHTMLString: page baseURL: requestURL]; ejecutará el Javascript en la página. He usado esta API con Google Maps.
jeff7091
3
NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];ha sido un salvavidas para mí varias veces ahora. Parece regresar del documento tanto como sea posible.
ennalax
2
@Hanuman Esto podría ayudarlo: NSString * head = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.head.innerHTML"]; NSString * body = [yourWebView stringByEvaluatingJavaScriptFromString: @ "document.body.innerHTML"]; NSString * totalPage = agregar ambas cadenas.
Deepukjayan
91

si desea extraer el contenido de un UIWebView ya cargado, -stringByEvaluatingJavaScriptFromString. Por ejemplo:

NSString  *html = [webView stringByEvaluatingJavaScriptFromString: @"document.body.innerHTML"];
Ben Gottlieb
fuente
10
Maldición, eso es inteligente!
jemmons
2
La pregunta que tengo es ¿qué sucede si el contenido es una cadena JSON o incluso una cadena sin formato sin una etiqueta de cuerpo?
stephenmuss
¡Esta no es una solución saludable! Todo el código javascript y la información del encabezado se pierden de esta manera.
Radu Simionescu
43

Para obtener todos los datos sin formato HTML (con <head>y <body>):

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

Tenga en cuenta que NSString stringWithContentsOfURL informará una cadena de agente de usuario totalmente diferente a la UIWebView que realiza la misma solicitud. Por lo tanto, si su servidor tiene conocimiento del agente de usuario y envía de vuelta diferentes html dependiendo de quién lo solicite, es posible que no obtenga los resultados correctos de esta manera.

También tenga en cuenta que lo @"document.body.innerHTML"mencionado anteriormente solo mostrará lo que está en la etiqueta del cuerpo. Si lo @"document.all[0].innerHTML"usas obtendrás cabeza y cuerpo. Que todavía no es el contenido completo de UIWebView, ya que no recuperará las etiquetas! Doctype o html, pero está mucho más cerca.

Pmatt
fuente
Teóricamente, podría obtener el doctype solicitándolo al servidor. Es probable que el doctype no cambie según el agente de uso.
Moshe
20

Leer:-

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

Modificar:-

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

En Swift v3:

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

Yo uso una extensión rápida como esta:

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

}
Nathan
fuente
1

deberías probar esto:

document.documentElement.outerHTML
schumyxp
fuente
1

UIWebView

obtener HTML de UIWebView`

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

establecer HTML en 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
}

[obtener / establecer HTML desde WKWebView]

yoAlex5
fuente