Di Android, saya memiliki WebView
yang menampilkan halaman.
Bagaimana cara mendapatkan sumber halaman tanpa meminta halaman itu lagi?
Tampaknya WebView
harus memiliki semacam getPageSource()
metode yang mengembalikan string, tetapi sayangnya tidak.
Jika saya mengaktifkan JavaScript, apa JavaScript yang sesuai untuk dimasukkan ke dalam panggilan ini untuk mendapatkan konten?
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
android
android-webview
gregm
sumber
sumber
Jawaban:
Saya tahu ini adalah jawaban yang terlambat, tetapi saya menemukan pertanyaan ini karena saya memiliki masalah yang sama. Saya rasa saya menemukan jawabannya dalam posting ini di lexandera.com. Kode di bawah ini pada dasarnya adalah potongan-dan-tempel dari situs. Tampaknya berhasil.
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");
sumber
onPageFinished()
dieksekusi.browser.loadUrl
dalamonPageFinished
akan menyebabkanonPageFinished
disebut lagi. Anda mungkin ingin memeriksa apakah ini panggilan pertamaonPageFinished
atau bukan sebelum meneleponbrowser.loadUrl
.String html = new Scanner(new DefaultHttpClient().execute(new HttpGet("www.the url")).getEntity().getContent(), "UTF-8").useDelimiter("\\A").next();
(disingkat agar sesuai dengan komentar :-))Per masalah 12987 , jawaban Blundell lumpuh (setidaknya di VM 2.3 saya). Sebagai gantinya, saya mencegat panggilan ke console.log dengan awalan khusus:
// 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");
sumber
Ini adalah jawaban berdasarkan jluckyiv's , tapi menurut saya lebih baik dan lebih sederhana untuk mengubah Javascript sebagai berikut.
browser.loadUrl("javascript:HTMLOUT.processHTML(document.documentElement.outerHTML);");
sumber
Pernahkah Anda mempertimbangkan untuk mengambil HTML secara terpisah, lalu memuatnya ke dalam tampilan 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; }
sumber
Saya berhasil mendapatkan ini bekerja menggunakan kode dari jawaban @ jluckyiv tetapi saya harus menambahkan anotasi @JavascriptInterface ke metode processHTML di MyJavaScriptInterface.
class MyJavaScriptInterface { @SuppressWarnings("unused") @JavascriptInterface public void processHTML(String html) { // process the html as needed by the app } }
sumber
Anda juga perlu menganotasi metode dengan @JavascriptInterface jika targetSdkVersion Anda> = 17 - karena ada persyaratan keamanan baru di SDK 17, yaitu semua metode javascript harus dianotasi dengan @JavascriptInterface. Jika tidak, Anda akan melihat kesalahan seperti: Uncaught TypeError: Object [object Object] tidak memiliki metode 'processHTML' pada null: 1
sumber
Jika Anda bekerja dengan kitkat dan yang lebih baru, Anda dapat menggunakan alat debugging jarak jauh chrome untuk menemukan semua permintaan dan tanggapan yang masuk dan keluar dari tampilan web Anda dan juga kode sumber html dari laman yang dilihat.
https://developer.chrome.com/devtools/docs/remote-debugging
sumber