1. Giới thiệu
Jsoup là một thư viện mạnh mẻ được sử dụng khá nhiều trong Android dùng để bóc tách các thành phần của html thành các đối tượng trong Java Android. Việc sử dụng Jsoup như thế nào thì bài viết này sẽ cùng các bạn khám phá.
Trang chủ của Jsoup: https://jsoup.org/
Bài viết sử dụng Android Studio 2.3
2.Cài đặt thư viện
Trước tiên mình tạo project có tên GuuJsoup bằng Android Studio vì mình sẽ bóc data trên trang guu.vn lý do up app lên bị google báo vi phạm bản quyền 😀
Thêm dependence trong file build.gradle
compile 'org.jsoup:jsoup:1.10.2'
Và các thư viện khác dưới đây:
compile 'com.android.support:cardview-v7:25.3.1' compile 'com.android.support:design:25.3.1' compile 'com.github.bumptech.glide:glide:3.7.0'
3. BẮT ĐẦU
Đầu tiên sẽ tiến hành tạo giao diện trước đơn giản như sau:
- Ở activity_main.xml tạo 1 RecyclerView dạng Gridview 3 cột
- Tạo 1 article_item.xml cho mỗi item hiển thị
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.lynkmieu.guujoup.MainActivity"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/recyler_category"/> </android.support.constraint.ConstraintLayout>
article_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView xmlns:cardView="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="true" cardView:cardUseCompatPadding="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/content_padding" android:paddingRight="@dimen/content_padding" android:layout_marginTop="8dp" android:orientation="vertical"> <ImageView android:id="@+id/img_thumbnail" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv_title" android:textSize="@dimen/title_size_text" android:textColor="#000" android:maxLines="2" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:text="4 tips mặc áo len cổ lọ thật phong cách trong ngày trở lạnh"/> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout>
Tiếp theo chúng ta sẽ tạo một Model để chứa dữ liệu parse từ web về như sau:
public class Article implements Serializable{ private String title; private String url; private String thumnail; private String decription; public Article() { } public Article(String title, String url, String thumnail, String decription) { this.title = title; this.url = url; this.thumnail = thumnail; this.decription = decription; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getThumnail() { return thumnail; } public void setThumnail(String thumnail) { this.thumnail = thumnail; } public String getDecription() { return decription; } public void setDecription(String decription) { this.decription = decription; } }
Tiếp theo tạo 1 adapter định nghĩa dữ liệu:
public class ArticleAdapter extends RecyclerView.Adapter<ArticleAdapter.ArticleHolder> { private Activity activity; private ArrayList<Article> listAticle; public ArticleAdapter(Activity activity, ArrayList<Article> listAticle) { this.activity = activity; this.listAticle = listAticle; } @Override public ArticleHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.article_item,parent,false); return new ArticleHolder(view); } @Override public void onBindViewHolder(final ArticleHolder holder, int position) { final Article article = listAticle.get(position); holder.tvTitle.setText(article.getTitle()); Glide.with(activity) .load(article.getThumnail()) .asBitmap() .atMost() .diskCacheStrategy(DiskCacheStrategy.ALL) .animate(android.R.anim.fade_in) .approximate() .into(holder.imgThumnal); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { activity.startActivity(new Intent(activity,DetailArticleActivity.class).putExtra("Article",article)); } }); } @Override public int getItemCount() { return listAticle.size(); } class ArticleHolder extends RecyclerView.ViewHolder{ private ImageView imgThumnal; private TextView tvTitle; public ArticleHolder(View itemView) { super(itemView); imgThumnal = (ImageView) itemView.findViewById(R.id.img_thumbnail); tvTitle = (TextView) itemView.findViewById(R.id.tv_title); } } }
Phần quan trọng ở MainActivity mình sẽ dùng AsycTask để download HTML và parse nó bằng Jsoup:
- Trang Web parse : https://guu.vn/cat/toc-dep
Các bạn chú ý phần này, mỗi một bài viết sẽ là 1 class col-md-6 trong đó sẽ chứa các thẻ h3 là tiêu đề, thẻ img, thẻ a là đường dẫn của bài viết chi tiết, thẻ h4 là decription
Bây giờ ở MainActivity.java các bạn sẽ code như sau:
- Config RecyclerView
- Khai báo URL cần parse
- Code AsyncTask download HTML
- Parse HTML
- set adapter cho recyclerView
public class MainActivity extends AppCompatActivity { public static final String MY_URL = "https://guu.vn/cat/toc-dep"; private RecyclerView recycler; private ArticleAdapter articleAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recycler = (RecyclerView) findViewById(R.id.recyler_category); configRecyclerView(); new DownloadTask().execute(MY_URL); } private void configRecyclerView() { RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this,3); recycler.hasFixedSize(); recycler.setLayoutManager(layoutManager); } //Download HTML bằng AsynTask private class DownloadTask extends AsyncTask<String, Void, ArrayList<Article>> { private static final String TAG = "DownloadTask"; @Override protected ArrayList<Article> doInBackground(String... strings) { Document document = null; ArrayList<Article> listArticle = new ArrayList<>(); try { document = (Document) Jsoup.connect(strings[0]).get(); if (document != null) { //Lấy html có thẻ như sau: div#latest-news > div.row > div.col-md-6 hoặc chỉ cần dùng div.col-md-6 Elements sub = document.select("div#latest-news > div.row > div.col-md-6"); for (Element element : sub) { Article article = new Article(); Element titleSubject = element.getElementsByTag("h3").first(); Element imgSubject = element.getElementsByTag("img").first(); Element linkSubject = element.getElementsByTag("a").first(); Element descrip = element.getElementsByTag("h4").first(); //Parse to model if (titleSubject != null) { String title = titleSubject.text(); article.setTitle(title); } if (imgSubject != null) { String src = imgSubject.attr("src"); article.setThumnail(src); } if (linkSubject != null) { String link = linkSubject.attr("href"); article.setUrl(link); } if (descrip != null) { String des = descrip.text(); article.setDecription(des); } //Add to list listArticle.add(article); } } } catch (IOException e) { e.printStackTrace(); } return listArticle; } @Override protected void onPostExecute(ArrayList<Article> articles) { super.onPostExecute(articles); //Setup data recyclerView articleAdapter = new ArticleAdapter(MainActivity.this,articles); recycler.setAdapter(articleAdapter); } } }
Dễ như ăn cháo luôn run app chúng ta có ngay kết quả như sau: D
Giờ bạn muốn phát triển tiếp trang detail thì trong adapter mình đã set sẵn cho các bạn hàm Onclick 😀
Hoặc code thêm để lấy đc toàn bộ dữ liệu từ guu.vn lưu về local 😀
Bình luận đã bị khoá.