W systemie Android mam, WebView
który wyświetla stronę.
Jak uzyskać źródło strony bez ponownego żądania strony?
Wydaje się, że WebView
powinien mieć jakąś getPageSource()
metodę zwracającą ciąg znaków, ale niestety tak nie jest.
Jeśli włączę JavaScript, jaki JavaScript powinien być umieszczony w tym wywołaniu, aby pobrać zawartość?
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
android
android-webview
gregm
źródło
źródło
Odpowiedzi:
Wiem, że to późna odpowiedź, ale znalazłem to pytanie, ponieważ miałem ten sam problem. Myślę, że znalazłem odpowiedź w tym poście na lexandera.com. Poniższy kod to w zasadzie wycinanie i wklejanie z witryny. Wydaje się, że to działa.
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");
źródło
onPageFinished()
wykonaniem.browser.loadUrl
wonPageFinished
spowodujeonPageFinished
nazywać ponownie. Możesz chcieć sprawdzić, czy jest to pierwsze połączenie,onPageFinished
czy nie, zanim zadzwoniszbrowser.loadUrl
.String html = new Scanner(new DefaultHttpClient().execute(new HttpGet("www.the url")).getEntity().getContent(), "UTF-8").useDelimiter("\\A").next();
(w skrócie, aby pasowało do komentarza :-))W numerze 12987 odpowiedź Blundella ulega awarii (przynajmniej na mojej maszynie wirtualnej 2.3). Zamiast tego przechwytuję wywołanie console.log ze specjalnym przedrostkiem:
// 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");
źródło
To jest odpowiedź oparta na jluckyiv's , ale myślę, że lepiej i łatwiej jest zmienić JavaScript w następujący sposób.
browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");
źródło
Czy rozważałeś pobranie kodu HTML osobno, a następnie załadowanie go do widoku internetowego?
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; }
źródło
Udało mi się to uruchomić, używając kodu z odpowiedzi @ jluckyiv, ale musiałem dodać adnotację @JavascriptInterface do metody processHTML w MyJavaScriptInterface.
class MyJavaScriptInterface { @SuppressWarnings("unused") @JavascriptInterface public void processHTML(String html) { // process the html as needed by the app } }
źródło
Musisz również dodać adnotację do metody @JavascriptInterface, jeśli twoja targetSdkVersion jest> = 17 - ponieważ w SDK 17 są nowe wymagania bezpieczeństwa, tj. Wszystkie metody javascript muszą być opatrzone adnotacją @JavascriptInterface. W przeciwnym razie zobaczysz błąd taki jak: Uncaught TypeError: Object [object Object] nie ma metody „processHTML” o wartości null: 1
źródło
Jeśli pracujesz na KitKat i nowszych wersjach, możesz użyć narzędzi do zdalnego debugowania chrome, aby znaleźć wszystkie żądania i odpowiedzi wchodzące i wychodzące z widoku internetowego, a także kod źródłowy html przeglądanej strony.
https://developer.chrome.com/devtools/docs/remote-debugging
źródło