web-dev-qa-db-fra.com

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

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

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");
148
jluckyiv

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");
32
durka42

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);");
17
nagoya0

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

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
    }
}
4
dr_sulli

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

1
javauser71

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.

https://developer.chrome.com/devtools/docs/remote-debugging

0
onusopus