làm thế nào để lấy nội dung html từ một trang web?


123

Phương pháp đơn giản nhất để lấy mã html từ chế độ xem web là gì? Tôi đã thử một số phương pháp từ stackoverflow và google, nhưng không thể tìm thấy phương pháp chính xác. Hãy đề cập một cách chính xác.

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

}

}

Câu trả lời:


107

Thực ra câu hỏi này có nhiều câu trả lời. Đây là 2 trong số chúng:

  • Đầu tiên này gần giống như của bạn, tôi đoán chúng ta đã lấy nó từ cùng một hướng dẫn.

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

    }
}

Bằng cách này, bạn lấy html thông qua javascript. Không phải là cách đẹp nhất nhưng khi bạn có giao diện javascript của mình, bạn có thể thêm các phương pháp khác để sửa đổi nó.


  • Một cách khác là sử dụng HttpClient như ở đó .

Tôi nghĩ tùy chọn bạn chọn cũng phụ thuộc vào những gì bạn định làm với html được truy xuất ...


khi thực thi dòng này webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");, chương trình hoạt động giống như hàm finish () và dừng hoạt động đó lại. tại sao? làm thế nào để giải quyết nó?

7
webview.addJavascriptInterface Chỉ hoạt động trên Jelly Beans và phiên bản thấp hơn.
xtr

32
Hai thay đổi quan trọng đối với mã trên cho Jellybean và mới hơn: 1. Loại bỏ "cửa sổ". từ dòng webview.loadUrl - giao diện javascript được đính kèm khác khi nhắm mục tiêu Jellybean. 2. Đặt @JavascriptInterface trước "public void showHTML" - điều này là cần thiết vì nó là một rủi ro bảo mật không chỉ cho phép một số phương thức được gọi.
karlbecker_com

1
Vẫn không hoạt động đối với tôi (5.1.1) .. Khi tôi thêm MyJavaScriptInterface (với gợi ý @karlbecker_com) khi tôi nhấp vào thứ gì đó trên hệ thống trang đã tải yêu cầu tôi chọn trình duyệt. Khi tôi xóa nó, nó sẽ không hỏi tôi nữa.
Makalele

1
Ở đây tôi cho phép gỡ lỗi từ xa, nó cho thấy Uncaught ReferenceError: HtmlViewer is not defined, cho dù có hoặc không có@JavascriptInterface
MewX

55

Trong KitKat trở lên, bạn có thể sử dụng evaluateJavascriptphương pháp trên 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
            }
    });

Xem câu trả lời này để biết thêm ví dụ


đây là bởi đến nay các giải pháp đơn giản nhất để sử dụng ở đây
Billy

9
FYI - Yêu cầu API 19.
Joel

7
Hãy nhớ đặt điều này vào phương thức onPageFinishing.
Cédric Portmann

@Joel Làm cách nào để đạt được điều này bên dưới API 19?
Pratik Saluja

1
@PratikSaluja vô cùng xin lỗi nếu bình luận của tôi truyền đạt sai ý. Câu trả lời với hầu hết các phiếu ủng hộ ở đây cũ hơn nhiều so với câu trả lời của riêng tôi và có thể sẽ phù hợp với bạn. Không có ý nghĩa gì ngoài điều đó. Rất vui vì bạn đã tìm thấy câu trả lời bằng cách xem BTW ở nơi khác.
Akash Kurian Jose


10

Android WebView chỉ là một công cụ kết xuất khác hiển thị nội dung HTML được tải xuống từ máy chủ HTTP, giống như Chrome hoặc FireFox. Tôi không biết lý do tại sao bạn cần tải trang (hoặc ảnh chụp màn hình) từ WebView. Đối với hầu hết các tình huống, điều này là không cần thiết. Bạn luôn có thể lấy trực tiếp nội dung HTML thô từ máy chủ HTTP.

Đã có những câu trả lời được đăng nói về việc nhận luồng thô bằng HttpUrlConnection hoặc HttpClient. Ngoài ra, có một thư viện rất tiện dụng khi xử lý quá trình / phân tích cú pháp nội dung HTML trên Android: JSoup , nó cung cấp API rất đơn giản để lấy nội dung HTML từ máy chủ HTTP và cung cấp bản trình bày trừu tượng của tài liệu HTML để giúp chúng tôi quản lý phân tích cú pháp HTML không chỉ theo phong cách OO hơn nhưng cũng dễ dàng hơn nhiều:

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

Ví dụ: sẽ rất hữu ích khi bạn muốn tải xuống tài liệu HTML trước, sau đó thêm một số css hoặc javascript tùy chỉnh vào nó trước khi chuyển nó đến WebView để hiển thị. Nhiều hơn nữa trên trang web chính thức của họ, đáng để xem.


5

Một điểm tiếp xúc mà tôi thấy rằng cần phải được đặt ra là "ẩn" trong cấu hình Proguard. Mặc dù trình đọc HTML gọi thông qua giao diện javascript chỉ tốt khi gỡ lỗi ứng dụng, điều này không còn hoạt động ngay khi ứng dụng được chạy qua Proguard, trừ khi chức năng đọc HTML được khai báo trong tệp cấu hình Proguard, như sau:

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

Đã kiểm tra và xác nhận trên Android 2.3.6, 4.1.1 và 4.2.1.


4

Android sẽ không cho phép bạn làm điều này vì lo ngại về bảo mật. Một nhà phát triển xấu rất có thể dễ dàng đánh cắp thông tin đăng nhập do người dùng nhập.

Thay vào đó, bạn phải nắm bắt văn bản đang được hiển thị trong chế độ xem web trước khi nó được hiển thị. Nếu bạn không muốn thiết lập trình xử lý phản hồi (theo các câu trả lời khác), tôi đã tìm thấy bản sửa lỗi này với một số 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();

Đây là rất nhiều mã, và bạn có thể sao chép / paster nó, và ở cuối mã strsẽ chứa cùng một html được vẽ trong webview. Câu trả lời này là từ cách Đơn giản nhất để tải chính xác html từ trang web thành một chuỗi trong Java và nó cũng sẽ hoạt động trên Android. Tôi đã không thử nghiệm điều này và không tự viết nó, nhưng nó có thể giúp ích cho bạn.

Ngoài ra, URL mà nó đang kéo được mã hóa cứng, vì vậy bạn sẽ phải thay đổi điều đó.


1

Tại sao không lấy html trước rồi chuyển nó vào chế độ xem 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);
            }
}

Điều này đại khái sẽ làm những gì bạn muốn làm. Nó được điều chỉnh từ Có thể lấy mã HTML từ WebView và gửi đến https://stackoverflow.com/users/325081/aymon-fournier để có câu trả lời.


HttpClient không được dùng nữa trong API Cấp 22 và bị xóa trong API Cấp 23. Vì vậy, các lớp được đề cập trong mã của bạn không thể được nhập vào các tệp java.
Dhananjay M

1

Tôi sẽ đề xuất thay vì cố gắng trích xuất HTML từ WebView, bạn trích xuất HTML từ URL. Điều này có nghĩa là tôi sử dụng thư viện của bên thứ ba như JSoup để duyệt qua HTML cho bạn. Đoạn mã sau sẽ lấy HTML từ một URL cụ thể cho bạn

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

giả sử url lấy được bằng cách đăng dữ liệu. phương pháp này sẽ thất bại.
Jafar Ali

Ngoài ra những gì về cookie?
Keith Adler

0

Đơn giản để thực hiện Chỉ cần các phương thức javasript trong html của bạn để nhận giá trị của nội dung html. Như trên mã của bạn cần có một số thay đổi.

  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 của bạn trong 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>

& Đảm bảo rằng bạn gọi callme như bên dưới trong html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Hy vọng điều này sẽ giúp bạn.


Điều này có nghĩa là gì & Make sure you calling callme like below in html. Ý của bạn là đặt thẻ đầu vào bên dưới tập lệnh trong tệp html? Thank You

không bạn phải gọi phương thức javasript callme () onblur của văn bản kiểu đầu vào trong thẻ html.
Ông Sajid Shaikh

sau đó thêm thẻ đầu vào này ở đâu. nút này có hiển thị không?

mã này hoạt động giống như, khi tải hoạt động, có một hộp văn bản trong chế độ xem web và văn bản đã nhập sẽ hiển thị ở hộp văn bản. Nhưng tôi muốn mã html trong chế độ xem web.

bạn có thể giúp tôi giải quyết vấn đề này không? Thank you very much

0

Tôi khuyên bạn nên thử một số phương pháp Phản chiếu, nếu bạn có thời gian dành cho trình gỡ lỗi (xin lỗi nhưng tôi không có).

Bắt đầu từ loadUrl()phương thức của android.webkit.WebViewlớp:

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

Bạn sẽ đến nơi android.webkit.BrowserFramegọi nativeLoadUrl()phương thức gốc:

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

Việc triển khai phương thức gốc sẽ ở đây:

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

Chúc bạn may mắn!


-1

hãy thử sử dụng HttpClient như Sephy đã nói:

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

bạn có thể hiển thị một cách đơn giản example.i làm việc không thể thực hiện mã của bạn trong ví dụ sephy của
KIRAN KJ

phương thức này sẽ lấy nguồn html của url đã cho. tức là getHtml ( google.com ); sẽ cung cấp cho bạn nguồn của trang chính của google
Christoper Hans

ok. có tùy chọn nào để lấy nguồn webview không. THANKS
KIRAN KJ

Điều này phần nào không hiệu quả với tôi. Tôi không nhận được bất kỳ nội dung nào từ một trang web thử nghiệm có nội dung là "hello world".
Momro

-2

Các phương pháp đã cho ở trên dành cho nếu bạn có một url web, nhưng nếu bạn có một html cục bộ thì bạn cũng có thể có html bằng mã này

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();
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.