Bir Web Görünümü'nden web sayfası içeriğini nasıl alırım?


86

Android'de WebViewbir sayfa görüntüleyen bir cihazım var.

Sayfayı tekrar istemeden sayfa kaynağını nasıl alırım?

Görünüşe göre bir dizge döndüren bir WebViewtür getPageSource()yöntemi olmalı , ama ne yazık ki yok.

JavaScript'i etkinleştirirsem, içeriği almak için bu çağrıya yerleştirilecek uygun JavaScript nedir?

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

webview window.interface.processHTML ($ (\ "body \"). html ()) 'den html içeriği almak için jquery komut dosyasını ve js arayüzünü kullanın;
DroidBot


HTTP İsteklerini kullanarak yanıtı açıkça HTML olarak alabilirsiniz, ancak bazı sayfalar gönderi verilerinin yüklenmesini gerektiriyorsa (örneğin, kullanıcı kimlik bilgileri vb.), Bu yaklaşım başarısız olur. Bence böyle olmalı çünkü eğer yapabilirseniz, muhtemelen herhangi bir web sitesi için kendi android uygulamanızı yapabilirsiniz ve bu berbat olurdu!

Yanıtlar:


162

Bunun geç bir cevap olduğunu biliyorum ama bu soruyu buldum çünkü aynı sorunu yaşadım. Sanırım cevabı lexandera.com'daki bu yazıda buldum. Aşağıdaki kod temelde siteden kesip yapıştır. Hile yapıyor gibi görünüyor.

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

6
Bunun sayfanın ham HTML'si olmayabileceğine dikkat edin; sayfa içeriği onPageFinished(), çalıştırılmadan önce JavaScript aracılığıyla dinamik olarak değişmiş olabilir .
Paul Lammertsma

3
Bu harika ama yöntemini çağırarak browser.loadUrliçinde onPageFinishedneden olacaktır onPageFinishedtekrar çağrılacak. Aramadan onPageFinishedönce ilk aramanın olup olmadığını kontrol etmek isteyebilirsiniz browser.loadUrl.
Yi H.

Teşekkürler @Blundell Bana çalıştı. Bunun bir hizmet olarak nasıl uygulanabileceğini bilmek istiyorum . Zira, sonuçları depolamak için düzeni ve web görünümü olmayan bir hizmettir. Verileri webView'dan farklı başka bir nesneye koymanın bir yolu var mı, böylece elde edilen html kodunu elde etmek için javascript'i koyabilir miyiz?
Totalys

@Totalys bu daha da kolay String html = new Scanner(new DefaultHttpClient().execute(new HttpGet("www.the url")).getEntity().getContent(), "UTF-8").useDelimiter("\\A").next();(bir yoruma sığacak şekilde kısaltılmıştır :-))
Blundell

1
RunOnUiThread (yeni Runnable () {... 'ı genel void işlem HTML'sine eklemeyi unutmayın.
CoolMind

34

Başına konuyla 12987 , Blundell cevabı (benim 2.3 VY'de en azından) çöker. Bunun yerine, özel bir önekle console.log'a yapılan bir çağrıyı durduruyorum:

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

17

Bu jluckyiv'lere dayanan bir cevaptır , ancak Javascript'i aşağıdaki gibi değiştirmenin daha iyi ve daha basit olduğunu düşünüyorum.

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

6

HTML'yi ayrı olarak getirmeyi ve ardından bir web görünümüne yüklemeyi düşündünüz mü?

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

2
Bu çerezleri taşımaz.
Keith Adler

1
bu yaklaşım CAPTCHA diyaloğunu tetikliyor
Hector

4

@ Jluckyiv'in cevabındaki kodu kullanarak bu çalışmayı başardım ama MyJavaScriptInterface'teki processHTML yöntemine @JavascriptInterface ek açıklamasını eklemek zorunda kaldım.

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

1

Ayrıca, targetSdkVersion> = 17 ise yönteme @JavascriptInterface ile açıklama eklemeniz gerekir - çünkü SDK 17'de yeni güvenlik gereksinimleri vardır, yani tüm javascript yöntemleri @JavascriptInterface ile açıklanmalıdır. Aksi takdirde, yakalanmamış TypeError: Nesnenin [nesne Nesnesi] null: 1'de 'processHTML' yöntemi yok gibi bir hata görürsünüz


-1

Kitkat ve üzeri üzerinde çalışıyorsanız, web görünümünüze giren ve çıkan tüm istekleri ve yanıtları ve ayrıca görüntülenen sayfanın html kaynak kodunu bulmak için krom uzaktan hata ayıklama araçlarını kullanabilirsiniz.

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


Soru, programlı olarak erişim sağlamak üzere. Gönderinizin ne kadar yararlı olduğunu açıklar mısınız?
Ajay Prajapati
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.