2010-03-04 30 views
71

Na Androidzie mam WebView, który wyświetla stronę.Jak uzyskać zawartość strony internetowej z WebView?

Jak uzyskać źródło strony bez ponownego żądania strony?

Wygląda na to, że WebView powinien mieć metodę getPageSource(), która zwraca ciąg, ale niestety nie.

Po włączeniu JavaScript, jaki jest odpowiedni kod JavaScript, aby wstawić to połączenie, aby uzyskać jego zawartość?

webview.loadUrl("javascript:(function() { " + 
    "document.getElementsByTagName('body')[0].style.color = 'red'; " + 
    "})()"); 
+0

użycie skrypt jQuery i JS interfejs, aby uzyskać zawartość HTML WebView window.interface.processHTML ($ (\ "ciało \") html().); – DroidBot

+0

http://stackoverflow.com/questions/8200945/how-to-get-html-content-from-a-webview?rq=1 – trante

+0

Oczywiście można uzyskać odpowiedź w HTML za pomocą żądań HTTP, ale jeśli strona wymaga załadowania danych pocztowych (jak na przykład poświadczenia użytkownika itp.), takie podejście po prostu nie powiedzie się. Myślę, że tak powinno być, ponieważ jeśli możesz to zrobić, prawdopodobnie możesz zrobić własną aplikację dla Androida na dowolnej stronie internetowej i to by było do dupy! –

Odpowiedz

134

Wiem, że to późna odpowiedź, ale znalazłem to pytanie, ponieważ miałem ten sam problem. Myślę, że znalazłem odpowiedź na stronie lexandera.com pod numerem this post. Poniższy kod jest w zasadzie wycinkiem i wklejaniem z witryny. Wydaje się, że to wystarczy.

+4

Pamiętaj, że może to nie być nieprzetworzony kod HTML strony; zawartość strony mogła ulec dynamicznej zmianie w JavaScript przed wykonaniem 'onPageFinished()'. –

+1

To świetnie, ale wywołanie metody 'browser.loadUrl' w' onPageFinished' spowoduje ponowne wywołanie 'onPageFinished'. Możesz chcieć sprawdzić, czy jest to pierwsze wywołanie 'onPageFinished', czy nie przed wywołaniem' browser.loadUrl'. –

+0

Dzięki @Blundell To zadziałało. Chciałbym wiedzieć, jak to może być ** zrealizowane jako usługa **. Ponieważ jest to usługa bez układu i przeglądarki internetowej do przechowywania wyników. Czy istnieje sposób na umieszczenie danych w jakimś innym obiekcie innym niż webView, abyśmy mogli umieścić javascript, aby uzyskać wynikowy kod HTML? – Totalys

31

Na issue 12987, odpowiedź Blundell ulega awarii (przynajmniej na moim 2.3 VM). Zamiast tego przechwycić wywołanie console.log ze specjalnym prefiksem:

// 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"); 
+1

Thx, działa to na 2.3.6 – Snicolas

17

ta jest odpowiedzią na podstawie jluckyiv's, ale myślę, że jest lepiej i prościej zmienić Javascript w następujący sposób.

browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);"); 
+0

Zapisałeś moją pracę !! :) – gior91

6

Czy rozważałeś pobranie osobno HTML, a następnie załadowanie go do wyświetlenia strony internetowej?

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

To nie będzie nosił ciasteczek. –

+0

to podejście uruchamia dialog CAPTCHA – Hector

4

udało mi się uzyskać tej pracy przy użyciu kodu z odpowiedzi użytkownika @ jluckyiv ale musiałem włożyć w @JavascriptInterface adnotacji metody processHTML w MyJavaScriptInterface.

class MyJavaScriptInterface 
{ 
    @SuppressWarnings("unused") 
    @JavascriptInterface 
    public void processHTML(String html) 
    { 
     // process the html as needed by the app 
    } 
} 
0

Należy również opisywanie metodę z @JavascriptInterface jeśli targetSdkVersion wynosi> = 17 - bo nie ma nowych wymogów bezpieczeństwa w SDK 17, to znaczy wszystkie javascript metody musi być odnotowany z @JavascriptInterface. W przeciwnym razie pojawi się błąd taki jak: Uncaught TypeError: Object [object Object] nie ma metody 'processHTML' pod adresem null: 1

Powiązane problemy