92 votes

Comment puis-je obtenir le contenu de la page Web à partir d'une WebView?

Sur Android, j'ai 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 renvoie une chaîne, mais ce n’est hélas pas le cas.

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'; " +  
    "})()");  
 

170voto

jluckyiv Points 2407

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 cet article sur lexandera.com. Le code ci-dessous est fondamentalement 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");
 

35voto

durka42 Points 311

Par 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");
 

18voto

nagoya0 Points 808

C’est une réponse basée sur celle de jluckyiv , 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);");
 

6voto

larham1 Points 2088

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;
}
 

4voto

dr_sulli Points 48

J'ai réussi à faire fonctionner cela en utilisant le code de la réponse de @ jluckyiv, mais je devais 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
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X