Sur Android, j'ai un WebView
qui affiche une page.
Comment obtenir le code source de la page sans demander à nouveau la page?
Il semble que WebView
devrait avoir une sorte de méthode getPageSource()
qui retourne une chaîne, mais hélas non.
Si j'active JavaScript, quel est le code JavaScript approprié pour cet appel afin d’obtenir le contenu?
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
Je sais que c'est une réponse tardive, mais j'ai trouvé cette question parce que j'avais le même problème. Je pense avoir trouvé la réponse dans ce post sur lexandera.com. Le code ci-dessous est essentiellement un copier-coller du site. Cela semble faire l'affaire.
final Context myApp = this;
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
@JavascriptInterface
@SuppressWarnings("unused")
public void processHTML(String html)
{
// process the html as needed by the app
}
}
final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
browser.getSettings().setJavaScriptEnabled(true);
/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url)
{
/* This call inject JavaScript into the page which just finished loading. */
browser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
}
});
/* load a web page */
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html");
Per numéro 12987 , la réponse de Blundell se bloque (au moins sur ma 2.3 VM). Au lieu de cela, j'intercepte un appel à console.log avec un préfixe spécial:
// intercept calls to console.log
web.setWebChromeClient(new WebChromeClient() {
public boolean onConsoleMessage(ConsoleMessage cmsg)
{
// check secret prefix
if (cmsg.message().startsWith("MAGIC"))
{
String msg = cmsg.message().substring(5); // strip off prefix
/* process HTML */
return true;
}
return false;
}
});
// inject the JavaScript on page load
web.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String address)
{
// have the page spill its guts, with a secret prefix
view.loadUrl("javascript:console.log('MAGIC'+document.getElementsByTagName('html')[0].innerHTML);");
}
});
web.loadUrl("http://www.google.com");
Ceci est une réponse basée sur jluckyiv's , mais je pense qu'il est préférable de changer le Javascript de la manière suivante.
browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");
Avez-vous envisagé d'extraire le code HTML séparément, puis de le charger dans une vue Web?
String fetchContent(WebView view, String url) throws IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse response = httpClient.execute(get);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
HttpEntity entity = response.getEntity();
String html = EntityUtils.toString(entity); // assume html for simplicity
view.loadDataWithBaseURL(url, html, "text/html", "utf-8", url); // todo: get mime, charset from entity
if (statusCode != 200) {
// handle fail
}
return html;
}
J'ai réussi à faire fonctionner cela en utilisant le code de la réponse de @ jluckyiv, mais j'ai dû ajouter une annotation @JavascriptInterface à la méthode processHTML dans MyJavaScriptInterface.
class MyJavaScriptInterface
{
@SuppressWarnings("unused")
@JavascriptInterface
public void processHTML(String html)
{
// process the html as needed by the app
}
}
Vous devez également annoter la méthode avec @JavascriptInterface si votre targetSdkVersion est> = 17 - car il existe de nouvelles exigences de sécurité dans le SDK 17, c'est-à-dire que toutes les méthodes javascript doivent être annotées avec @JavascriptInterface. Sinon, vous verrez une erreur comme: Uncaught TypeError: Object [objet Object] n'a pas de méthode 'processHTML' à null: 1
Si vous travaillez sur KitKat et versions ultérieures, vous pouvez utiliser les outils de débogage à distance chrome) pour rechercher toutes les demandes et réponses entrant et sortant de votre vue Web, ainsi que le code source HTML de la page. vu.