bir web görünümünden html içeriği nasıl alınır?


123

Bir web görünümünden html kodunu almanın en basit yöntemi hangisidir? Stackoverflow ve google'dan birkaç yöntem denedim, ancak kesin bir yöntem bulamıyorum. Lütfen tam olarak bir yol belirtin.

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

}

}

Yanıtlar:


107

Aslında bu sorunun birçok cevabı var. İşte bunlardan 2 tanesi:

  • Bu ilki neredeyse sizinkiyle aynı, sanırım onu ​​aynı eğitimden aldık.

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

    }
}

Bu şekilde html'yi javascript aracılığıyla yakalarsınız. En güzel yol değil ama javascript arayüzünüz olduğunda, onu düzeltmek için başka yöntemler de ekleyebilirsiniz.


  • Başka bir yol da oradaki gibi bir HttpClient kullanmaktır .

Seçtiğiniz seçenek, bence, alınan html ile ne yapmak istediğinize de bağlıdır ...


bu satırı çalıştırdığınızda webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");program finish () işlevi gibi davranır ve bu etkinliği durdurur. neden? nasıl çözülür?

7
webview.addJavascriptInterface Yalnızca Jelly Beans ve daha düşük sürümlerde çalışır.
xtr

32
Jellybean ve sonrası için yukarıdaki kodda iki önemli değişiklik: 1. "window" öğesini kaldırın. webview.loadUrl satırından - Jellybean hedeflenirken javascript arayüzü farklı şekilde eklenir. 2. @JavascriptInterface'i "public void showHTML" den önce koyun - bu gereklidir, çünkü yalnızca belirli yöntemlerin çağrılmasına izin vermek bir güvenlik riski değildir.
karlbecker_com

1
Hala benim için çalışmıyor (5.1.1) .. MyJavaScriptInterface eklerken (@karlbecker_com ipuçları ile) yüklü sayfa sistemindeki bir şeyi tıkladığımda tarayıcı seçmemi istiyor. Bunu kaldırdığımda bana bir daha sormayacak.
Makalele

1
Burada uzaktan hata ayıklamayı etkinleştirdim, gösterdi Uncaught ReferenceError: HtmlViewer is not defined, olsun ya da olmasın@JavascriptInterface
MewX

55

KitKat ve üstünde, evaluateJavascriptyöntemi web görünümünde kullanabilirsiniz

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

Daha fazla örnek için bu yanıta bakın


bu, burada kullanmak için açık ara en kolay çözüm
Billy

9
Bilginize - API 19 gerektirir.
Joel,

7
Bunu onPageFinished yöntemine koymayı unutmayın.
Cédric Portmann

@Joel API 19'un altında bunu nasıl başarabilirim?
Pratik Saluja

1
@PratikSaluja yorumum yanlış bir fikir verdiyse çok üzgünüm. Buradaki çoğu olumlu oyla verilen cevap, kendi cevabımdan çok daha eskidir ve muhtemelen sizin için işe yarar. Bunun ötesinde bir şey ifade etmedi. Cevabı başka bir yere bakarak bulduğunuza çok sevindim BTW.
Akash Kurian Jose


10

Android WebView, Chrome veya FireFox gibi bir HTTP sunucusundan indirilen HTML içeriğini işleyen başka bir işleme motorudur. WebView'dan oluşturulan sayfayı (veya ekran görüntüsünü) almanızın nedenini bilmiyorum. Çoğu durumda bu gerekli değildir. Ham HTML içeriğini her zaman doğrudan HTTP sunucusundan alabilirsiniz.

HttpUrlConnection veya HttpClient kullanarak ham akışı almaktan bahseden yanıtlar zaten var. Alternatif olarak, Android: JSoup üzerinde HTML içerik ayrıştırma / işleme ile uğraşırken çok kullanışlı bir kitaplık vardır, HTML içeriğini HTTP sunucusundan almak için çok basit bir API sağlar ve sadece HTML ayrıştırmayı yönetmemize yardımcı olmak için HTML belgesinin soyut bir temsilini sağlar. daha OO tarzında ama aynı zamanda çok kolay:

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

Örneğin, önce HTML belgesini indirmek istediğinizde, ardından işleme için WebView'a geçirmeden önce ona bazı özel css veya javascript eklemek istediğinizde kullanışlıdır. Resmi web sitelerinde çok daha fazlası, kontrol etmeye değer.


5

Yerine konulması gereken bir temas noktası Proguard yapılandırmasında "gizli". HTML okuyucu, uygulamada hata ayıklarken javascript arayüzü aracılığıyla gayet iyi bir şekilde çalışsa da, Proguard yapılandırma dosyasında HTML okuyucu işlevi bildirilmediği sürece, uygulama Proguard aracılığıyla çalıştırılır çalıştırılmaz artık çalışmaz:

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

Android 2.3.6, 4.1.1 ve 4.2.1'de test edildi ve onaylandı.


4

Android, güvenlik endişeleriniz için bunu yapmanıza izin vermez. Kötü bir geliştirici, kullanıcı tarafından girilen giriş bilgilerini çok kolay bir şekilde çalabilir.

Bunun yerine, web görünümünde görüntülenen metni görüntülenmeden önce yakalamanız gerekir. Bir yanıt işleyicisi kurmak istemiyorsanız (diğer yanıtlara göre), bu düzeltmeyi bir miktar google'da buldum:

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

Bu çok fazla koddur ve onu kopyalayıp / paster yapabilmelisiniz ve sonunda strweb görünümünde çizilen aynı html'yi içerecektir. Bu cevap, html'yi web sayfasından Java'daki bir dizeye doğru şekilde yüklemenin en basit yoludur ve Android'de de çalışmalıdır. Bunu test etmedim ve kendim yazmadım, ancak size yardımcı olabilir.

Ayrıca, bunun çektiği URL kodlanmış, bu yüzden bunu değiştirmeniz gerekecek.


1

Neden önce html'yi alıp sonra web görünümüne geçirmiyorsunuz?

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

Bu, kabaca yapmak istediğiniz şeyi yapmalıdır. Uyarlanmıştır mümkün WebView'da HTML kodu almak için İş'in ve haykırmak https://stackoverflow.com/users/325081/aymon-fournier onun cevabını.


HttpClient, API Seviye 22'de kullanımdan kaldırıldı ve API Seviye 23'te kaldırıldı. Dolayısıyla, kodunuzda belirtilen sınıflar java dosyalarında içe aktarılamaz.
Dhananjay M

1

HTML'yi Web Görünümünden çıkarmaya çalışmak yerine, HTML'yi URL'den çıkarmanızı öneririm. Bununla, sizin için HTML'de gezinmek için JSoup gibi bir üçüncü taraf kitaplığı kullanmayı kastediyorum. Aşağıdaki kod HTML'yi sizin için belirli bir URL'den alacak

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

veri göndererek elde edilen url'ye ulaşıldığını varsayalım. bu yöntem başarısız olacaktır.
Jafar Ali

Ayrıca çerezler ne olacak?
Keith Adler

0

Uygulaması basittir html içeriğinin değerini elde etmek için html'nizde javasript yöntemlerine ihtiyacınız var. Kodunuzun üstünde olduğu gibi bazı değişikliklere ihtiyaç vardır.

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

    }

}

HTML'deki Javascript'iniz

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

& Callme'yi html'de aşağıdaki gibi aradığınızdan emin olun

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Umarım bu sana yardımcı olur.


Bu ne anlama geliyor & Make sure you calling callme like below in html? Girdi etiketini html dosyasında komut dosyasının altına yerleştirmek mi istediniz? Thank You

hayır dostum, html etiketindeki giriş türü metnin javasript yöntemi callme () onblur'u çağırmanız gerekir.
Bay Sajid Shaikh

o zaman bu giriş etiketi nereye eklenir. bu düğme görünür mü?

Bu kod, etkinlik yüklenirken web görünümünde bir metin kutusu var ve yazılan metin metin kutusunda göründüğü gibi çalışır, ancak html kodunu web görünümünde istiyorum.

bu sorunu çözmeme yardım edebilir misin? Thank you very much

0

Hata ayıklayıcı üzerinde harcayacak vaktiniz varsa (üzgünüm ama sahip olmadım), biraz Yansıma yaklaşımını denemenizi öneririm.

Sınıfın loadUrl()yönteminden başlayarak android.webkit.WebView:

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

Bu android.webkit.BrowserFrameçağrıya nativeLoadUrl()yerel yöntemi ulaşmanız gerekir :

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

Yerel yöntemin uygulanması burada olmalıdır:

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

Size iyi şanslar diliyorum!


-1

Sephy'nin dediği gibi HttpClient kullanmayı deneyin:

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

basit bir çalışma örneği gösterebilir misiniz? kodunuzu sephy örneğinde uygulayamıyorum
KIRAN KJ

bu yöntem, verilen url'nin html kaynağını alacaktır. yani getHtml ( google.com ); size google ana sayfasının kaynağını getirecek
Christoper Hans

Tamam. web görünümü kaynağını almak için herhangi bir seçenek var. THANKS
KIRAN KJ

Bu benim için bir şekilde işe yaramadı. Bir test sitesinden "merhaba dünya" olan herhangi bir içerik almadım.
Momro

-2

yukarıda verilen yöntemler bir web url'niz varsa içindir, ancak yerel bir html'niz varsa, bu kodla html'ye de sahip olabilirsiniz

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();
        }
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.