come ottenere contenuto html da una visualizzazione web?


123

Qual è il metodo più semplice per ottenere codice html da una visualizzazione web? Ho provato diversi metodi da stackoverflow e google, ma non riesco a trovare un metodo esatto. Si prega di menzionare un modo esatto.

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

}

}

Risposte:


107

In realtà questa domanda ha molte risposte. Eccone 2:

  • Questo primo è quasi uguale al tuo, immagino che l'abbiamo preso dallo stesso tutorial.

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

    }
}

In questo modo prendi l'html tramite javascript. Non è il modo più carino, ma quando hai la tua interfaccia javascript, puoi aggiungere altri metodi per armeggiarla.


  • Un altro modo è usare un HttpClient come .

L'opzione che scegli dipende anche, credo, da cosa intendi fare con l'html recuperato ...


quando si esegue questa riga webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");il programma si comporta come la funzione finish () e interrompe quell'attività. perché? come risolverlo?

7
webview.addJavascriptInterface Funziona solo su Jelly Beans e versioni precedenti.
xtr

32
Due importanti modifiche al codice precedente per Jellybean e versioni successive: 1. Rimuovere "window". dalla riga webview.loadUrl - l'interfaccia javascript è collegata in modo diverso quando si targetizza Jellybean. 2. Metti @JavascriptInterface prima di "public void showHTML" - questo è necessario poiché è un rischio per la sicurezza non consentire solo a determinati metodi di essere chiamati.
karlbecker_com

1
Ancora non funziona per me (5.1.1) .. Quando aggiungo MyJavaScriptInterface (con i suggerimenti @karlbecker_com) quando faccio clic su qualcosa sulla pagina caricata, il sistema mi chiede di scegliere il browser. Quando lo rimuovo, non me lo chiederà più.
Makalele

1
Qui ho abilitato il debug remoto, ha mostrato Uncaught ReferenceError: HtmlViewer is not defined, non importa con o senza@JavascriptInterface
MewX

55

In KitKat e versioni successive, puoi usare il evaluateJavascriptmetodo su webview

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

Vedi questa risposta per altri esempi


questa è di gran lunga la soluzione più semplice da usare qui
Billy

9
FYI - Richiede API 19.
Joel

7
Ricorda di metterlo nel metodo onPageFinished.
Cédric Portmann

@ Joel Come ottenere questo risultato sotto l'API 19?
Pratik Saluja

1
@PratikSaluja estremamente dispiaciuto se il mio commento ha trasmesso l'idea sbagliata. La risposta con la maggior parte dei voti positivi qui è molto più vecchia della mia risposta e probabilmente funzionerebbe per te. Non significava niente oltre a quello. Molto contento che tu abbia trovato la risposta cercando altrove BTW.
Akash Kurian Jose il

41

Per Android 4.2, non dimenticare di aggiungere @JavascriptInterface a tutte le funzioni javasscript


1
Funziona per Android 4.2 e SOPRA.
Cédric Portmann

10

Android WebView è solo un altro motore di rendering che esegue il rendering di contenuti HTML scaricati da un server HTTP, proprio come Chrome o FireFox. Non so il motivo per cui è necessario ottenere la pagina renderizzata (o screenshot) da WebView. Per la maggior parte delle situazioni, questo non è necessario. Puoi sempre ottenere il contenuto HTML grezzo direttamente dal server HTTP.

Sono già state pubblicate risposte che parlano di come ottenere il flusso non elaborato utilizzando HttpUrlConnection o HttpClient. In alternativa, c'è una libreria molto utile quando si ha a che fare con l'analisi / elaborazione del contenuto HTML su Android: JSoup , fornisce un'API molto semplice per ottenere contenuti HTML dal server HTTP e fornisce una rappresentazione astratta del documento HTML per aiutarci a gestire non solo l'analisi HTML in uno stile più OO ma anche molto facilmente:

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

È utile quando, ad esempio, si desidera scaricare prima un documento HTML, quindi aggiungere un css o javascript personalizzato prima di passarlo a WebView per il rendering. Molto di più sul loro sito web ufficiale, vale la pena dare un'occhiata.


5

Un punto di contatto che ho scoperto che deve essere messo in atto è "nascosto" nella configurazione Proguard. Mentre il lettore HTML invoca correttamente l'interfaccia javascript durante il debug dell'app, non funziona più non appena l'app è stata eseguita tramite Proguard, a meno che la funzione del lettore HTML non sia dichiarata nel file di configurazione Proguard, in questo modo:

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

Testato e confermato su Android 2.3.6, 4.1.1 e 4.2.1.


4

Android non ti consente di farlo per motivi di sicurezza. Uno sviluppatore malvagio potrebbe facilmente rubare le informazioni di accesso inserite dall'utente.

Invece, devi catturare il testo visualizzato nella visualizzazione Web prima che venga visualizzato. Se non vuoi impostare un gestore di risposte (come per le altre risposte), ho trovato questa correzione con alcuni 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();

Questo è un sacco di codice e dovresti essere in grado di copiarlo / incollarlo, e alla fine strconterrà lo stesso html disegnato nella visualizzazione web. Questa risposta proviene dal modo più semplice per caricare correttamente html dalla pagina web in una stringa in Java e dovrebbe funzionare anche su Android. Non l'ho testato e non l'ho scritto da solo, ma potrebbe aiutarti.

Inoltre, l'URL che viene estratto è codificato, quindi dovrai cambiarlo.


1

Perché non scaricare prima l'html e poi passarlo alla visualizzazione 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);
            }
}

Questo dovrebbe fare più o meno quello che vuoi fare. È adattato da È possibile ottenere il codice HTML da WebView e gridare a https://stackoverflow.com/users/325081/aymon-fournier per la sua risposta.


HttpClient è stato deprecato nel livello API 22 e rimosso nel livello API 23. Pertanto le classi menzionate nel codice non possono essere importate nei file java.
Dhananjay M

1

Suggerirei invece di provare a estrarre l'HTML da WebView, di estrarre l'HTML dall'URL. Con questo, intendo usare una libreria di terze parti come JSoup per attraversare l'HTML per te. Il codice seguente otterrà l'HTML da un URL specifico per te

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

supponiamo che l'URL ottenuto venga raggiunto inserendo i dati. questo metodo fallirà.
Jafar Ali

E anche i cookie?
Keith Adler,

0

È semplice da implementare Basta usare i metodi javasript nel tuo html per ottenere valore dal contenuto html. Come sopra il tuo codice alcune modifiche sono necessarie.

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

    }

}

Il tuo Javascript in 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>

& Assicurati di chiamare callme come sotto in html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Spero che questo ti possa aiutare.


cosa significa & Make sure you calling callme like below in html. Intendevi inserire il tag di input sotto lo script nel file html? Thank You

no amico devi chiamare il metodo javasript callme () onblur del tipo di testo di input nel tag html.
Mr. Sajid Shaikh

allora dove aggiungere questo tag di input. questo pulsante è visibile?

questo codice funziona come, durante il caricamento dell'attività c'è una casella di testo nella visualizzazione web e il testo digitato viene mostrato nella casella di testo. Ma voglio il codice html nella visualizzazione web.

puoi aiutarmi a risolvere questo problema? Thank you very much

0

Suggerisco di provare un approccio di riflessione, se hai tempo da dedicare al debugger (scusate ma non avevo).

A partire dal loadUrl()metodo della android.webkit.WebViewclasse:

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

Dovresti arrivare a android.webkit.BrowserFramequella chiamata al nativeLoadUrl()metodo nativo:

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

L'implementazione del metodo nativo dovrebbe essere qui:

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

Ti auguro buona fortuna!


-1

prova a utilizzare HttpClient come ha detto 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;
}

puoi mostrare un semplice esempio funzionante. non posso implementare il tuo codice nell'esempio di sephy
KIRAN KJ

questo metodo otterrà l'origine html dell'URL fornito. cioè getHtml ( google.com ); ti fornirà la fonte della pagina principale di Google
Christoper Hans,

è ok. c'è qualche opzione per ottenere la fonte di visualizzazione web. THANKS
KIRAN KJ

Questo in qualche modo non ha funzionato per me. Non ho ricevuto alcun contenuto da un sito di prova il cui contenuto fosse stato "ciao mondo".
Momro

-2

i metodi sopra indicati sono per se hai un URL web, ma se hai un html locale allora puoi avere anche html con questo codice

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();
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.