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