如何从WebView获取html内容?


123

从网络视图获取html代码的最简单方法是什么?我已经尝试了stackoverflow和google的几种方法,但是找不到确切的方法。请提及确切方法。

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

}

}

Answers:


107

其实这个问题有很多答案。这是其中的两个:

  • 第一个与您的几乎相同,我想我们是从同一教程中获得的。

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

    }
}

这样,您就可以通过javascript抓取html。不是最漂亮的方法,但是当您拥有JavaScript界面​​时,可以添加其他方法进行修改。


  • 另一种方法是使用HttpClient的喜欢那里

我认为,您选择的选项还取决于您打算对检索到的html进行处理...


当执行此行时webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");,程序的行为类似于函数finish(),并停止该活动。为什么?如何解决呢?

7
webview.addJavascriptInterface仅适用于Jelly Bean和更低版本。
xtr

32
对上述Jellybean及更高版本的代码进行了两项重要更改:1.删除“窗口”。从webview.loadUrl行开始-定位Jellybean时,javascript界面​​的连接方式有所不同。2.将@JavascriptInterface放在“ public void showHTML”之前-这是必要的,因为存在安全隐患,不仅允许调用某些方法。
karlbecker_com

1
仍然对我不起作用(5.1.1)。当我在加载的页面上单击某些东西时,当我添加MyJavaScriptInterface(带有@karlbecker_com提示)时,系统要求我选择浏览器。当我删除它时,它不会再询问我。
Makalele,2015年

1
Uncaught ReferenceError: HtmlViewer is not defined无论是否启用,我都在这里启用了远程调试功能@JavascriptInterface
MewX

55

在KitKat及更高版本中,您可以evaluateJavascript在webview上使用method

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

查看答案以获取更多示例


这是迄今为止最简单的解决方案,利用这里
比利

9
仅供参考-需要
Joel

7
请记住将其放入onPageFinished方法中。
塞德里克·波特曼(CédricPortmann)

@Joel如何在API 19下实现此目标?
Pratik Saluja

1
如果我的评论传达了错误的想法,@ PratikSaluja非常抱歉。这里投票最多的答案比我自己的答案年代久远,可能对您有用。没什么意思。很高兴您在其他地方看到了答案,找到了答案。
Akash Kurian Jose


10

Android WebView只是另一个渲染引擎,可渲染从HTTP服务器下载的HTML内容,就像Chrome或FireFox。我不知道为什么需要从WebView获取呈现的页面(或屏幕截图)的原因。对于大多数情况,这不是必需的。您始终可以直接从HTTP服务器直接获取原始HTML内容。

已经发布了有关使用HttpUrlConnection或HttpClient获取原始流的答案。另外,在Android上处理HTML内容解析/过程时,有一个非常方便的库:JSoup,它提供了非常简单的API从HTTP服务器获取HTML内容,并提供了HTML文档的抽象表示,不仅帮助我们管理HTML解析,以更OO的风格,但也很容易:

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

例如,当您要先下载HTML文档,然后向其中添加一些自定义css或javascript,然后再将其传递到WebView进行渲染时,此操作非常方便。在其官方网站上有更多内容,值得一查。


5

我发现需要放置的一个接触点在Proguard配置中被“隐藏”了。尽管HTML阅读器在调试应用程序时可以通过javascript界面​​很好地调用,但是除非通过Proguard配置文件声明了HTML阅读器功能,否则只要通过Proguard运行应用程序,此操作就不再起作用。

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

在Android 2.3.6、4.1.1和4.2.1上测试并确认。


4

出于安全考虑,Android不允许您这样做。邪恶的开发人员很容易窃取用户输入的登录信息。

相反,您必须先捕获Web视图中显示的文本,然后才能显示该文本。如果您不想设置响应处理程序(按照其他答案),我可以通过使用Google搜索找到此修复程序:

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

这是很多代码,您应该能够复制/粘贴它,并且在结尾处str将包含在webview中绘制的相同html。这个答案是从最简单的方法正确地将网页中的html加载到Java中的字符串中的并且它也应该在Android上也可以使用。我没有测试过它,也没有自己写过,但是可能会对您有所帮助。

另外,要提取的URL是硬编码的,因此您必须进行更改。


1

为什么不先获取html然后将其传递到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);
            }
}

这应该大致做您想做的事。改编自《是否可以从WebView获取HTML代码 并大声疾呼至https://stackoverflow.com/users/325081/aymon-fournier以获取答案》。


HttpClient在API级别22中已弃用,在API级别23中已删除。因此,代码中提到的类无法导入到Java文件中。
Dhananjay M

1

我建议您不要尝试从WebView提取HTML,而应从URL提取HTML。我的意思是使用第三方库(例如JSoup)为您遍历HTML。以下代码将从您的特定URL获取HTML

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

假设通过发布数据到达url获取。此方法将失败。
Jafar Ali 2014年

饼干呢?
基思·阿德勒

0

它实现简单,只需在HTML中使用javasript方法即可获取html内容的价值。如上面的代码所示,需要进行一些更改。

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

&确保您在html中调用如下的callme

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
希望这会帮助你。


这是什么意思& Make sure you calling callme like below in html。您的意思是将输入标签放在html文件中的脚本下方吗? Thank You

没有花哨的人,您不必在html标记中调用输入类型文本的javasript方法callme()onblur。
Sajid Shaikh先生2012年

然后在哪里添加此输入标签。此按钮是否可见?

此代码的工作方式类似,在加载活动时,webview中有一个文本框,键入的文本显示在该文本框中。但是我要在webview中使用html代码。

你能帮我解决这个问题吗?Thank you very much

0

-1

尝试使用HttpClient,如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;
}

您可以显示一个简单的工作示例
吗?我

此方法将获取给定URL的html源。即getHtml(google.com); 将为您提供Google主页的来源
Christoper Hans

ok.is是否有任何选项可获取webview源。THANKS
KIRAN KJ 2012年

这有点对我不起作用。我没有从测试站点获得任何内容,这些内容一直是​​“ hello world”。
Momro

-2

上面给出的方法适用于您是否具有网址的情况,但是如果您具有本地html,则可以通过此代码获得html

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();
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.