Crawl Data from Html

Nhiều khi chúng ta muốn lấy dữ liệu trên các trang web, ví dụ lấy truyện, bài báo,ảnh hoặc get link nhạc từ các trang nghe nhạc trực tuyến.... Nếu những dữ liệu đó được hiển thị trên trang web, thì hoàn toàn có thể lấy được. Ở đây mình sẽ sử dụng Jsoup để lấy 1 số dữ liệu đơn giản trên web

Đầu tiên cần xem mã nguồn của trang web đó, ở đây mình sẽ ví dụ là trang web http://khongphailanhatky.blogspot.com/2015/11/test.html

Sau đó cần xác định 1 số thông tin để xác định chính xác chỗ cần lấy thông tin, id.PNG

ở đây mình sẽ xác định id của bài viết cần crawl về, bên trong thẻ này có 3 thẻ <category>, <title> và <content>. Như vậy là đã xác định xong các thành phần cần lấy thông tin, tiếp theo sẽ thực hiện code chương trình.

Đầu tiên khai báo INTERNET permission trong Manifest, và import thư viện Jsoup:

jsoup.PNG

Sau đó tạo layout trong activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
    </android.support.design.widget.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_category"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:textSize="20sp"
                android:textStyle="bold|italic" />

            <TextView
                android:id="@+id/tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/tv_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:textSize="15sp" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

Tiếp theo là sử dụng Jsoup để get html code về và parse để lấy thông tin trong MainActivity Thứ tự các bước sẽ là:

  1. Lấy toàn bộ html trang web về
  2. Tìm trong đó element chứa bài viết
  3. Lấy các thông tin trong bài viết và hiển thị, (thông tin trong các thẻ <category>, <title>, <content>)
public class MainActivity extends AppCompatActivity {
    private ProgressDialog progressDialog;
    private TextView tvCategory;
    private TextView tvTitle;
    private TextView tvContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        progressDialog = new ProgressDialog(this);
        tvCategory = (TextView) findViewById(R.id.tv_category);
        tvTitle = (TextView) findViewById(R.id.tv_title);
        tvContent = (TextView) findViewById(R.id.tv_content);

        String path = "http://khongphailanhatky.blogspot.com/2015/11/test.html";
        String idPost = "post-body-8881203422069576330";
        URL url;
        try {
            url = new URL(path);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            Toast.makeText(this, "URL is invalid", Toast.LENGTH_SHORT).show();
            return;
        }

        GetContentFromURL getContentFromURL = new GetContentFromURL(url, idPost);
        getContentFromURL.execute();
    }

    private class GetContentFromURL extends AsyncTask<Void, Void, Document> {
        private URL url;
        private String idPost;

        public GetContentFromURL(URL url, String idPost) {
            this.url = url;
            this.idPost = idPost;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog.setMessage("Please wait ...");
            progressDialog.setCancelable(false);
            progressDialog.show();
        }

        @Override
        protected Document doInBackground(Void... params) {
            try {
                Document elements = Jsoup.connect(url.toString()).get();
                return elements;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onPostExecute(Document document) {
            super.onPostExecute(document);
            if (document != null) {
                Element element = Jsoup.parse(document.toString()).select("#" + idPost).first();
                Elements listElement = element.getAllElements();
                String category = "", title = "", content = "";
                for (int i = 0; i < listElement.size(); i++) {
                    Element childElement = listElement.get(i);
                    switch (childElement.tagName()) {
                        case "category":
                            if (childElement.hasText()) {
                                category = childElement.text();
                            }
                            break;
                        case "title":
                            title = childElement.text();
                            break;
                        case "content":
                            String outputText = childElement.text();

                            String inputTextStart = outputText.replace("\\n ", "\n");
                            String inputTextFinal = inputTextStart.replace("\\n", "\n");
                            content = inputTextFinal;
                            break;
                    }
                }
                tvCategory.setText(category);
                tvTitle.setText(title);
                tvContent.setText(content);
            } else {
                Toast.makeText(MainActivity.this, "Get Data Fail", Toast.LENGTH_SHORT).show();
            }
            progressDialog.dismiss();
        }
    }

Một điều cần chú ý là nếu find theo id thì trước key cần có ký tự '#'. Tham khảo use selector tại http://jsoup.org/cookbook/extracting-data/selector-syntax

Kết quả:

Screenshot_2016-01-24-14-02-05[1].jpg

Thank you for reading, happy cold day to everyone!