bagaimana cara mendapatkan konten html dari tampilan web?

123

Manakah metode paling sederhana untuk mendapatkan kode html dari tampilan web? Saya telah mencoba beberapa metode dari stackoverflow dan google, tetapi tidak dapat menemukan metode yang tepat. Harap sebutkan cara yang tepat.

public class htmldecoder extends Activity implements OnClickListener,TextWatcher
{
TextView txturl;
Button btgo;
WebView wvbrowser;
TextView txtcode;
ImageButton btcode;
LinearLayout llayout;
int flagbtcode;
public void onCreate(Bundle savedInstanceState)
{
            super.onCreate(savedInstanceState);
                setContentView(R.layout.htmldecoder);

    txturl=(TextView)findViewById(R.id.txturl);

    btgo=(Button)findViewById(R.id.btgo);
    btgo.setOnClickListener(this);

    wvbrowser=(WebView)findViewById(R.id.wvbrowser);
    wvbrowser.setWebViewClient(new HelloWebViewClient());
    wvbrowser.getSettings().setJavaScriptEnabled(true);
    wvbrowser.getSettings().setPluginsEnabled(true);
    wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    wvbrowser.addJavascriptInterface(new MyJavaScriptInterface(),"HTMLOUT");
    //wvbrowser.loadUrl("http://www.google.com");
    wvbrowser.loadUrl("javascript:window.HTMLOUT.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");


    txtcode=(TextView)findViewById(R.id.txtcode);
    txtcode.addTextChangedListener(this);

    btcode=(ImageButton)findViewById(R.id.btcode);
    btcode.setOnClickListener(this);

    }

public void onClick(View v)
{
    if(btgo==v)
    {
        String url=txturl.getText().toString();
        if(!txturl.getText().toString().contains("http://"))
        {
            url="http://"+url;
        }
        wvbrowser.loadUrl(url);
        //wvbrowser.loadData("<html><head></head><body><div style='width:100px;height:100px;border:1px red solid;'></div></body></html>","text/html","utf-8");
    }
    else if(btcode==v)
    {
        ViewGroup.LayoutParams params1=wvbrowser.getLayoutParams();
        ViewGroup.LayoutParams params2=txtcode.getLayoutParams();
        if(flagbtcode==1)
        {
            params1.height=200;
            params2.height=220;
            flagbtcode=0;
            //txtcode.setText(wvbrowser.getContentDescription());
        }
        else
        {
            params1.height=420;
            params2.height=0;
            flagbtcode=1;
        }
        wvbrowser.setLayoutParams(params1);
        txtcode.setLayoutParams(params2);

    }
}

public class HelloWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        view.loadUrl(url);
        return true;
    }
    /*@Override
    public void onPageFinished(WebView view, String url)
    {
        // This call inject JavaScript into the page which just finished loading. 
        wvbrowser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }*/

}
class MyJavaScriptInterface
{
    @SuppressWarnings("unused")
    public void showHTML(String html)
    {

        txtcode.setText(html);
    }
}

public void afterTextChanged(Editable s) {
    // TODO Auto-generated method stub

}

public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
    // TODO Auto-generated method stub

}

public void onTextChanged(CharSequence s, int start, int before, int count) {
    wvbrowser.loadData("<html><div"+txtcode.getText().toString()+"></div></html>","text/html","utf-8");

}

}
Hope4You
sumber

Jawaban:

107

Sebenarnya pertanyaan ini punya banyak jawaban. Berikut 2 di antaranya:

  • Yang pertama ini hampir sama dengan milik Anda, saya rasa kami mendapatkannya dari tutorial yang sama.

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.webview);
        final WebView webview = (WebView) findViewById(R.id.browser);
        webview.getSettings().setJavaScriptEnabled(true);
        webview.addJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");

        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                webview.loadUrl("javascript:window.HtmlViewer.showHTML" +
                        "('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
            }
        });

        webview.loadUrl("http://android-in-action.com/index.php?post/" +
                "Common-errors-and-bugs-and-how-to-solve-avoid-them");
    }

    class MyJavaScriptInterface {

        private Context ctx;

        MyJavaScriptInterface(Context ctx) {
            this.ctx = ctx;
        }

        public void showHTML(String html) {
            new AlertDialog.Builder(ctx).setTitle("HTML").setMessage(html)
                    .setPositiveButton(android.R.string.ok, null).setCancelable(false).create().show();
        }

    }
}

Dengan cara ini Anda mengambil html melalui javascript. Bukan cara tercantik tetapi ketika Anda memiliki antarmuka javascript, Anda dapat menambahkan metode lain untuk mengotak-atiknya.


  • Cara lain adalah menggunakan HttpClient seperti di sana .

Opsi yang Anda pilih juga tergantung, menurut saya, pada apa yang ingin Anda lakukan dengan html yang diambil ...

Sephy
sumber
ketika menjalankan baris ini webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");program bertindak seperti fungsi finish (), dan menghentikan aktivitas itu. mengapa? bagaimana menyelesaikannya?
7
webview.addJavascriptInterface Hanya berfungsi pada Jelly Beans dan versi yang lebih rendah.
xtr
32
Dua perubahan penting pada kode di atas untuk Jellybean dan yang lebih baru: 1. Hapus "jendela". dari baris webview.loadUrl - antarmuka javascript dipasang secara berbeda saat menargetkan Jellybean. 2. Letakkan @JavascriptInterface sebelum "public void showHTML" - ini diperlukan karena risiko keamanan tidak hanya mengizinkan pemanggilan metode tertentu.
karlbecker_com
1
Masih tidak berhasil untuk saya (5.1.1) .. Ketika saya menambahkan MyJavaScriptInterface (dengan petunjuk @karlbecker_com) ketika saya mengklik sesuatu pada sistem halaman yang dimuat meminta saya untuk memilih browser. Saat saya menghapus ini, aplikasi tidak akan meminta saya lagi.
Makalele
1
Di sini saya mengaktifkan debugging jarak jauh, itu menunjukkan Uncaught ReferenceError: HtmlViewer is not defined, tidak peduli dengan atau tanpa@JavascriptInterface
MewX
55

Di KitKat dan di atasnya, Anda dapat menggunakan evaluateJavascriptmetode di tampilan web

wvbrowser.evaluateJavascript(
        "(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();",
         new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String html) {
                Log.d("HTML", html); 
                // code here
            }
    });

Lihat jawaban ini untuk contoh lainnya

Akash Kurian Jose
sumber
Sejauh ini, ini adalah solusi termudah untuk digunakan di sini
Billy
9
FYI - Membutuhkan API 19.
Joel
7
Ingatlah untuk memasukkan ini ke dalam metode onPageFinished.
Cédric Portmann
@ Joel Bagaimana mencapai ini di bawah API 19?
Pratik Saluja
1
@PratikSaluja sangat menyesal jika komentar saya menyampaikan gagasan yang salah. Jawaban dengan suara positif terbanyak di sini jauh lebih tua dari jawaban saya sendiri dan mungkin akan berhasil untuk Anda. Tidak berarti apa-apa di luar itu. Sangat senang Anda menemukan jawabannya dengan mencari di tempat lain BTW.
Akash Kurian Jose
41

Untuk Android 4.2, jangan lupa menambahkan @JavascriptInterface ke semua fungsi javasscript

pengguna1842354
sumber
1
Bekerja untuk android 4.2 dan DI ATAS.
Cédric Portmann
10

Android WebView hanyalah mesin render lain yang merender konten HTML yang diunduh dari server HTTP, seperti Chrome atau FireFox. Saya tidak tahu alasan mengapa Anda perlu mendapatkan halaman yang dirender (atau tangkapan layar) dari WebView. Untuk sebagian besar situasi, ini tidak perlu. Anda selalu bisa mendapatkan konten HTML mentah dari server HTTP secara langsung.

Sudah ada jawaban yang diposting berbicara tentang mendapatkan aliran mentah menggunakan HttpUrlConnection atau HttpClient. Sebagai alternatif, ada pustaka yang sangat berguna saat menangani penguraian / proses konten HTML di Android: JSoup , ini menyediakan API yang sangat sederhana untuk mendapatkan konten HTML dari server HTTP, dan menyediakan representasi abstrak dari dokumen HTML untuk membantu kami mengelola penguraian HTML tidak hanya dalam gaya yang lebih OO tetapi juga lebih mudah:

// Single line of statement to get HTML document from HTTP server.
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();

Ini berguna ketika, misalnya, Anda ingin mengunduh dokumen HTML terlebih dahulu, lalu menambahkan beberapa css atau javascript khusus ke dokumen tersebut sebelum meneruskannya ke WebView untuk dirender. Lebih banyak lagi di situs web resmi mereka, layak untuk dicoba.

yorkw
sumber
5

Satu titik sentuh yang saya temukan yang perlu diterapkan adalah "tersembunyi" di konfigurasi Proguard. Meskipun pembaca HTML memanggil melalui antarmuka javascript dengan baik saat men-debug aplikasi, ini tidak lagi berfungsi segera setelah aplikasi dijalankan melalui Proguard, kecuali jika fungsi pembaca HTML dideklarasikan dalam file konfigurasi Proguard, seperti:

-keepclassmembers class <your.fully.qualified.HTML.reader.classname.here> {
    public *; 
}

Diuji dan dikonfirmasi di Android 2.3.6, 4.1.1 dan 4.2.1.

pengguna1756541
sumber
4

Android tidak akan membiarkan Anda melakukan ini untuk masalah keamanan. Pengembang jahat dapat dengan mudah mencuri informasi login yang dimasukkan pengguna.

Sebagai gantinya, Anda harus menangkap teks yang sedang ditampilkan di webview sebelum ditampilkan. Jika Anda tidak ingin menyiapkan penangan respons (sesuai jawaban lain), saya menemukan perbaikan ini dengan beberapa googling:

URL url = new URL("/programming/1381617");
URLConnection con = url.openConnection();
Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*");
Matcher m = p.matcher(con.getContentType());
/* If Content-Type doesn't match this pre-conception, choose default and 
 * hope for the best. */
String charset = m.matches() ? m.group(1) : "ISO-8859-1";
Reader r = new InputStreamReader(con.getInputStream(), charset);
StringBuilder buf = new StringBuilder();
while (true) {
  int ch = r.read();
  if (ch < 0)
    break;
  buf.append((char) ch);
}
String str = buf.toString();

Ini adalah kode yang banyak, dan Anda harus dapat menyalin / memasukkannya, dan pada akhirnya strakan berisi html yang sama yang digambar dalam tampilan web. Jawaban ini berasal dari cara termudah untuk memuat html dengan benar dari halaman web ke dalam string di Java dan seharusnya berfungsi di Android juga. Saya belum menguji ini dan tidak menulisnya sendiri, tapi mungkin bisa membantu Anda.

Selain itu, URL yang ditarik adalah hardcode, jadi Anda harus mengubahnya.

edthethird
sumber
1

Mengapa tidak mendapatkan html terlebih dahulu lalu meneruskannya ke tampilan web?

private String getHtml(String url){
    HttpGet pageGet = new HttpGet(url);

    ResponseHandler<String> handler = new ResponseHandler<String>() {
        public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
            HttpEntity entity = response.getEntity();
            String html; 

            if (entity != null) {
                html = EntityUtils.toString(entity);
                return html;
            } else {
                return null;
            }
        }
    };

    pageHTML = null;
    try {
        while (pageHTML==null){
            pageHTML = client.execute(pageGet, handler);
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return pageHTML;
}

@Override
public void customizeWebView(final ServiceCommunicableActivity activity, final WebView webview, final SearchResult mRom) {
    mRom.setFileSize(getFileSize(mRom.getURLSuffix()));
    webview.getSettings().setJavaScriptEnabled(true);
    WebViewClient anchorWebViewClient = new WebViewClient()
    {

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);

            //Do what you want to with the html
            String html = getHTML(url);

            if( html!=null && !url.equals(lastLoadedURL)){
                lastLoadedURL = url;
                webview.loadDataWithBaseURL(url, html, null, "utf-8", url);
            }
}

Ini kira-kira harus melakukan apa yang ingin Anda lakukan. Ini diadaptasi dari Apakah mungkin untuk mendapatkan kode HTML dari WebView dan berteriak ke https://stackoverflow.com/users/325081/aymon-fournier untuk jawabannya.

Karl L.
sumber
HttpClient sudah tidak digunakan lagi di API Level 22 dan dihapus di API Level 23. Jadi kelas yang disebutkan dalam kode Anda tidak dapat diimpor di file java.
Dhananjay M
1

Saya akan menyarankan daripada mencoba mengekstrak HTML dari WebView, Anda mengekstrak HTML dari URL. Dengan ini, maksud saya menggunakan perpustakaan pihak ketiga seperti JSoup untuk melintasi HTML untuk Anda. Kode berikut akan mendapatkan HTML dari URL tertentu untuk Anda

public static String getHtml(String url) throws ClientProtocolException, IOException {
        HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = httpClient.execute(httpGet, localContext);
        String result = "";

        BufferedReader reader = new BufferedReader(
            new InputStreamReader(
                response.getEntity().getContent()
            )
        );

        String line = null;
        while ((line = reader.readLine()) != null){
            result += line + "\n";
        }
        return result;
    }
Mimminito
sumber
misalkan perolehan url dicapai dengan memposting data. metode ini akan gagal.
Jafar Ali
Juga bagaimana dengan cookie?
Keith Adler
0

Sederhana untuk diimplementasikan Hanya perlu metode javasript di html Anda untuk mendapatkan nilai konten html. Seperti Di atas kode Anda, beberapa perubahan perlu dilakukan.

  public class htmldecoder extends Activity implements OnClickListener,TextWatcher
    {
    Button btsubmit; // this button in your xml file
    WebView wvbrowser;
    public void onCreate(Bundle savedInstanceState)
    {
                super.onCreate(savedInstanceState);
                    setContentView(R.layout.htmldecoder);



        btsubmit=(Button)findViewById(R.id.btsubmit);
        btsubmit.setOnClickListener(this);

        wvbrowser=(WebView)findViewById(R.id.wvbrowser);
        wvbrowser.setWebViewClient(new HelloWebViewClient());
        wvbrowser.getSettings().setJavaScriptEnabled(true);
        wvbrowser.getSettings().setPluginsEnabled(true);
        wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        MyJavaScriptInterface myinterface=new MyJavaScriptInterface();
        wvbrowser.addJavascriptInterface(myinterface,"interface");
        webView.loadUrl("file:///android_asset/simple.html");  //use one html file for //testing put your html file in assets. Make sure that you done JavaScript methods to get //values for html content in html file . 
   }
   public void onClick(View v)
{
    if(btsubmit==v)
    {

        webView.loadUrl("javascript:showalert()");// call javascript method.  
        //wvbr
    }
}

final class MyJavaScriptInterface {



        MyJavaScriptInterface() {

        }

        public void sendValueFromHtml(String value) {
           System.out.println("Here is the value from html::"+value);
        }

    }

}

Javascript Anda dalam html

 <script type="text/javascript">
    //<![CDATA[
    var n1;
    function callme(){
    n1=document.getElementById("FacadeAL").value;
    }
    function showalert(){
     window.interface.sendValueFromHtml(n1);// this method calling the method of interface which //you attached to html file in android. // & we called this showalert javasript method on //submmit buttton click of android. 
    }
    //]]>
    </script>

& Pastikan Anda menelepon callme seperti di bawah ini di html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Semoga ini bisa membantu Anda.

Tuan Sajid Shaikh
sumber
apa artinya ini. & Make sure you calling callme like below in htmlApakah Anda bermaksud menempatkan tag input di bawah skrip dalam file html? Thank You
tidak sobat Anda harus memanggil metode javasript callme () onblur teks jenis input dalam tag html.
Tn. Sajid Shaikh
lalu di mana menambahkan tag input ini. apakah tombol ini terlihat?
kode ini berfungsi seperti, saat memuat aktivitas ada kotak teks di tampilan web dan teks yang diketik muncul di kotak teks. Tapi saya ingin kode html di tampilan web.
dapatkah kamu membantu saya untuk menyelesaikan masalah ini? Thank you very much
0

Saya sarankan untuk mencoba beberapa pendekatan Refleksi, jika Anda punya waktu untuk dihabiskan untuk debugger (maaf tapi saya tidak punya).

Mulai dari loadUrl()metode android.webkit.WebViewkelas:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/WebView.java#WebView.loadUrl%28java.lang.String % 2Cjava.util.Map% 29

Anda harus sampai pada android.webkit.BrowserFramepanggilan itu dengan nativeLoadUrl()metode native:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/BrowserFrame.java#BrowserFrame.nativeLoadUrl%28java.lang.String % 2Cjava.util.Map% 29

Penerapan metode asli seharusnya ada di sini:

http://gitorious.org/0xdroid/external_webkit/blobs/a538f34148bb04aa6ccfbb89dfd5fd784a4208b1/WebKit/android/jni/WebCoreFrameBridge.cpp

Semoga Anda beruntung!

lechuckcaptain
sumber
-1

coba gunakan HttpClient seperti yang dikatakan Sephy:

public String getHtml(String url) {
    HttpClient vClient = new DefaultHttpClient();
    HttpGet vGet = new HttpGet(url);
    String response = "";    

    try {
        ResponseHandler<String> vHandler = new BasicResponseHandler();
        response = vClient.execute(vGet, vHandler);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return response;
}
Christoper Hans
sumber
dapatkah Anda menunjukkan contoh yang berfungsi sederhana. saya tidak dapat menerapkan kode Anda dalam contoh sephy
KIRAN KJ
metode ini akan mendapatkan sumber html dari url yang diberikan. yaitu getHtml ( google.com ); akan memberi Anda sumber halaman utama google
Christoper Hans
tidak apa-apa. apakah ada opsi untuk mendapatkan sumber tampilan web. THANKS
KIRAN KJ
Ini agak tidak berhasil untuk saya. Saya tidak mendapatkan konten apa pun dari situs pengujian yang isinya adalah "halo dunia".
Momro
-2

metode yang diberikan di atas adalah untuk jika Anda memiliki url web, tetapi jika Anda memiliki html lokal maka Anda juga dapat memiliki html dengan kode ini

AssetManager mgr = mContext.getAssets();
             try {
InputStream in = null;              
if(condition)//you have a local html saved in assets
                            {
                            in = mgr.open(mFileName,AssetManager.ACCESS_BUFFER);
                           }
                            else if(condition)//you have an url
                            {
                            URL feedURL = new URL(sURL);
                  in = feedURL.openConnection().getInputStream();}

                            // here you will get your html
                 String sHTML = streamToString(in);
                 in.close();

                 //display this html in the browser or web view              


             } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
             }
        public static String streamToString(InputStream in) throws IOException {
            if(in == null) {
                return "";
            }

            Writer writer = new StringWriter();
            char[] buffer = new char[1024];

            try {
                Reader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));

                int n;
                while ((n = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, n);
                }

            } finally {

            }

            return writer.toString();
        }
vipin
sumber