como obter conteúdo html de uma visualização na web?

123

Qual é o método mais simples de obter código html em uma visualização na web? Eu tentei vários métodos de stackoverflow e google, mas não consigo encontrar um método exato. Por favor mencione uma maneira exata.

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
fonte

Respostas:

107

Na verdade, esta pergunta tem muitas respostas. Aqui estão 2 deles:

  • Este primeiro é quase o mesmo que o seu, acho que conseguimos no mesmo 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();
        }

    }
}

Desta forma, você pega o html através do javascript. Não é a maneira mais bonita, mas quando você tem sua interface javascript, você pode adicionar outros métodos para mexer nela.


  • Uma outra maneira é usar um HttpClient como esse .

A opção que você escolhe também depende, penso eu, do que você pretende fazer com o html recuperado ...

Sephy
fonte
ao executar esta linha, webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");o programa age como a função finish () e interrompe essa atividade. por que? como resolvê-lo?
7
webview.addJavascriptInterface Funciona apenas em Jelly Beans e na versão inferior.
XTR
32
Duas mudanças importantes no código acima para o Jellybean e posteriores: 1. Remova a "janela". da linha webview.loadUrl - a interface javascript é anexada de maneira diferente ao segmentar o Jellybean. 2. Coloque @JavascriptInterface antes de "public void showHTML" - isso é necessário, pois é um risco de segurança não apenas permitir a chamada de certos métodos.
28413 karlecker_com
1
Ainda não funciona para mim (5.1.1). Quando adiciono MyJavaScriptInterface (com dicas @karlbecker_com) quando clico em algo no sistema de páginas carregado, solicito que escolha o navegador. Quando eu removo isso, ele não me pergunta novamente.
21315 Makalele
1
Aqui eu habilitado a depuração remota, ele mostrou Uncaught ReferenceError: HtmlViewer is not defined, não importa com ou sem@JavascriptInterface
MewX
55

No KitKat e acima, você pode usar o evaluateJavascriptmétodo na visualização na 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
            }
    });

Veja esta resposta para mais exemplos

Akash Kurian Jose
fonte
este é de longe a solução mais fácil de usar aqui
Billy
9
FYI - Requer API 19.
Joel
7
Lembre-se de colocar isso no método onPageFinished.
Cédric Portmann
@Joel Como conseguir isso abaixo da API 19?
Pratik Saluja
1
@PratikSaluja extremamente triste se meu comentário transmitiu a idéia errada. A resposta com a maioria dos votos positivos aqui é muito mais antiga que a minha e provavelmente funcionaria para você. Não significava nada além disso. Muito feliz que você encontrou a resposta procurando em outro lugar.
Akash Kurian Jose
41

Para o Android 4.2, não se esqueça de adicionar @JavascriptInterface em todas as funções javasscript

user1842354
fonte
1
Funciona para o Android 4.2 e acima.
Cédric Portmann
10

O Android WebView é apenas outro mecanismo de renderização que renderiza o conteúdo HTML baixado de um servidor HTTP, como o Chrome ou o FireFox. Não sei o motivo pelo qual você precisa obter a página renderizada (ou captura de tela) do WebView. Para a maioria das situações, isso não é necessário. Você sempre pode obter o conteúdo HTML bruto do servidor HTTP diretamente.

Já existem respostas postadas falando sobre como obter o fluxo bruto usando HttpUrlConnection ou HttpClient. Como alternativa, existe uma biblioteca muito útil ao lidar com a análise / processo de conteúdo HTML no Android: JSoup , ela fornece uma API muito simples para obter conteúdo HTML do servidor HTTP e fornece uma representação abstrata do documento HTML para nos ajudar a gerenciar a análise HTML não apenas em um estilo mais OO, mas também com muita facilidade:

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

É útil quando, por exemplo, você deseja fazer o download do documento HTML primeiro e depois adicionar algum CSS ou javascript personalizado antes de passá-lo ao WebView para renderização. Muito mais em seu site oficial, vale a pena conferir.

yorkw
fonte
5

Um ponto de contato que eu descobri que precisa ser colocado no lugar é "escondido" na configuração do Proguard. Enquanto o leitor HTML chama pela interface javascript muito bem ao depurar o aplicativo, isso não funciona mais assim que o aplicativo foi executado através do Proguard, a menos que a função do leitor HTML seja declarada no arquivo de configuração Proguard, da seguinte maneira:

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

Testado e confirmado no Android 2.3.6, 4.1.1 e 4.2.1.

user1756541
fonte
4

O Android não permitirá que você faça isso por questões de segurança. Um desenvolvedor malvado pode facilmente roubar informações de login inseridas pelo usuário.

Em vez disso, você deve capturar o texto que está sendo exibido na webview antes de ser exibido. Se você não deseja configurar um manipulador de respostas (conforme as outras respostas), eu encontrei essa correção com algumas pesquisas:

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

Isso é muito código, e você deve poder copiá-lo / alterá-lo e, no final, strconterá o mesmo html desenhado na visualização na web. Esta resposta é da maneira mais simples de carregar corretamente html da página da web em uma string em Java e deve funcionar no Android também. Eu não testei isso e não o escrevi, mas isso pode ajudá-lo.

Além disso, o URL que está puxando é codificado permanentemente, então você terá que mudar isso.

edthethird
fonte
1

Por que não obter o html primeiro e depois passá-lo para a visualização na 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);
            }
}

Isso deve fazer aproximadamente o que você quer fazer. É adaptado de É possível obter o código HTML do WebView e gritar para https://stackoverflow.com/users/325081/aymon-fournier por sua resposta.

Karl L
fonte
HttpClient foi descontinuado no nível 22 da API e removido no nível 23 da API. Portanto, as classes mencionadas no seu código não podem ser importadas nos arquivos java.
Dhananjay M
1

Sugiro que, em vez de tentar extrair o HTML do WebView, você extraia o HTML da URL. Com isso, quero dizer usando uma biblioteca de terceiros, como JSoup, para percorrer o HTML para você. O código a seguir obterá o HTML de um URL específico para você

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
fonte
suponha que a obtenção da URL seja alcançada postando dados. esse método falhará.
Jafar Ali #
E os cookies?
Keith Adler
0

É simples de implementar. Só precisa de métodos javasript no seu html para obter valor do conteúdo html. Como acima do seu código, algumas alterações serão necessárias.

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

    }

}

Seu Javascript em 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>

& Certifique-se de ligar para o callme como abaixo em html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Espero que isso ajude você.

Mr. Sajid Shaikh
fonte
o que isso significa & Make sure you calling callme like below in html. Você quis colocar a tag de entrada abaixo do script no arquivo html? Thank You
cara, você precisa chamar o método javasript callme () onblur do texto do tipo de entrada na tag html.
Mr. Sajid Shaikh
onde adicionar esta tag de entrada. esse botão está visível?
esse código funciona como, ao carregar a atividade, há uma caixa de texto no webview e o texto digitado é exibido na caixa de texto. Mas eu quero o código html no webview.
você pode me ajudar a resolver esse problema? Thank you very much
0

Sugiro tentar uma abordagem de reflexão, se você tiver tempo para gastar no depurador (desculpe, mas eu não tinha).

A partir do loadUrl()método da 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

Você deve chegar ao android.webkit.BrowserFrameque chama o nativeLoadUrl()método 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

A implementação do método nativo deve estar aqui:

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

Desejo boa sorte!

lechuckcaptain
fonte
-1

tente usar o HttpClient como Sephy disse:

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
fonte
você pode mostrar um simples trabalho example.i não pode implementar o seu código no exemplo de Sephy
KIRAN KJ
esse método obterá a fonte html do URL fornecido. ou seja, getHtml ( google.com ); você irá obter o código fonte da página principal do Google
Christoper Hans
está ok. existe alguma opção para obter a fonte do webview. THANKS
KIRAN KJ
Isso não funcionou para mim. Não obtive nenhum conteúdo de um site de teste cujo conteúdo fosse "olá mundo".
Momro
-2

Os métodos acima mencionados são para se você tiver um URL da Web, mas se você tiver um html local, também poderá ter um html com este código

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
fonte