Android: Jsoup Kütüphanesi ve HTML Parser

Merhaba arkadaşlar,

Bugün Android ile html parse etme işlemini bunun içinde kullanacağımız jsoup kütüphanesinden bahsedeceğim. Bu dersi Eclipse ortamında anlatacağım. Öncelikle buradan Jsoup kütüphanesini indiriyoruz (jsoup-1.8.1.jar), indirdiğimiz jar dosyasını projemize dahil ettikten sonra artık kullanabiliriz. Peki ne işe yarar Jsoup kütüphanesi? Bu kütüphane ile hızlı bir şekilde html parse etme işlemi gerçekleştirilmektedir. Android uygulamalarda sıkça kullanılan RSS kaynaklardır, ancak bazı web sitelerinde RSS kaynağının bulunmaması bizi html parse etme işlemine sürükler. Bu yüzden bu kütüphaneyi kullanmayı tercih ve tavsiye ediyorum.

Öncelikle yapacağımız projenin kısa bir hikayesini yazalım. Bu projede oguzhanozdemir.com.tr web adresimin basit bir uygulamasını geliştirmeye çalışacağım. Uygulama içerisinde son yazıları listeyeceğiz. Yazılarımızın başlığı, adresi, resmi ve kısa içeriği bulunacaktır.

Jsoup kütüphanesinde istediğimiz alanların html ve css taglarını belirleyerek kaynak dosya içerisinde geçen verileri Element listesi olarak tutulmasını sağlıyoruz. Bu yüzden ilk işlemimiz sitemizdeki title, content, image gibi alanların taglarını belirlemek olacaktır. Sitemizin kaynak dosyasına göz atalım.

jsoup

Şekilde sitemizde bizi sonuca ulaştıracak div tagları ve bu div tagları içerisinde img, h2, p gibi diğer son taglar işaretlenmiştir. Burada önemli olan nokta div taglarının özel isimleridir. Örneğin bazı div taglarının ID’lerini alırken bazılarının ise Class isimlerini alacağız. Diğer önemli nokta ise hızlı olması açısından her adımda bir alttaki tag’a ulaşacağız. Basamak basamak ilerleyeceğiz.

Şimdi uygulamamıza dönelim. Uygulamamızın ana sayfasında bir adet ListView bulunacaktır. Bu listview’in her satırının özel olan görselini ayarlayarak başlayabiliriz.

row

Üst kısımda yazımızın başlığı, hemen altında görselimiz ve altında da kısa içeriğimiz bulunacaktır. Seçilen itemin ayrıntısını görmek için ise görünmez olarak bulundurduğumuz bir textview nesnemiz daha vardır.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_marginBottom="5dp"
 android:orientation="vertical" >
<TextView
 android:id="@+id/txtTitle"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Large Text"
 android:layout_gravity="center"
 android:layout_margin="2dp"
 android:textAppearance="?android:attr/textAppearanceLarge" />
<ImageView
 android:id="@+id/imagePost"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center"
 android:layout_marginBottom="2dp"
 android:src="@drawable/ic_launcher" />
 
 <ir.noghteh.JustifiedTextView
 xmlns:noghteh="http://noghteh.ir"
 android:id="@+id/txtContent"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:layout_gravity="left"
 android:layout_margin="2dp"
 noghteh:text="asdasd">
 </ir.noghteh.JustifiedTextView>
<TextView
 android:id="@+id/txtAddress"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:visibility="gone"
 android:text="TextView" />
</LinearLayout>

 

Kodlarımızda da görüldüğü gibi 3 adet textview ve 1 adet imageview nesnesi bulunmaktadır.(txtAddress id’li textview nesnemiz arkaplanda işimizi göreceği için visibility = gone yaptık). Ayrıca incelemenizi tavsiye ettiğim JustifiedTextView kütüphanesini de kullandım, bu kütüphane içerisinde barındırdığı paragrafı sağa ve sola yaslı olarak hizalamaktadır. Hızlı bir şekilde MainActivity’nin de arayüzünü oluşturan xml dosyasına göz atalım.

  • activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="com.ogzhnozdmr.jsouplib.MainActivity" >
<ListView
 android:id="@+id/listPosts"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:layout_alignParentLeft="true"
 android:layout_alignParentTop="true" >
 </ListView>
</RelativeLayout>

 

Uygulama içerisinde activity_main.xml de bulunan listview ile verileri listeleyeceğiz. Gelen verileri ise oluşturacağımız bir nesne de tutmalıyız. Yani her bir satır 1 nesneyi ifade etmeli, bizim nesnemiz de Post olsun. Her post’umuzun bir başlığı, resmi, içeriği ve adresi bulunmaktadır demiştik. Bu bilgiler ışığında nesnemizin classını yazdık.

post_class

Şimdiki işlemimiz ise verileri kaynak dosyamızdan çekmek ve parse etmek. Yani asıl konumuza geldik. Genel itibariyle android programlama içerisinde web’den veri çekme işlemleri AsyncTask nesnesi ile arka planda yapılmaktadır. Bizde html parse işlemlerimizi AsyncTask ile yapacağız. İlk olarak 2 adet AsyncTask sınıfı oluşturuyoruz bu sınıfların kodlarını göstermeden önce gerçekleştirilecek işlemlerden bahsetmek istiyorum.(AsyncTask hakkında.)

İlk sınıfımız GetLastPosts sınıfı, bu sınıf String parametre alarak çalışmaktadır. Biz de parametre olarak sitemizin adresini vereceğiz, “http://www.oguzhanozdemir.com.tr”. AsyncTask sınıfı birkaç fonksiyondan oluşmaktadır. Bizde bu fonksiyonları Override ederek işlemlerimizi gerçekleştireceğiz. onPreExecute, doInBackground ve onPostExecute metotları. doInBackground metodunun en önemli 2 özelliği; yapılmak istenen işlemler burada gerçekleştirilir (örneğin webden  veri çekmek..) diğeri ise bu metot içerisinde hiç bir şekilde arayüze müdahale edemiyoruz. Genellikle arayüze postExecute metodunda işlem sonunda gösterilmek istenen sonuçlar için müdahale edebiliyoruz. Son olarak onPreExecute metotunda ise progressDialog ile kullanıcıyı bilgilendiriyoruz.

GetLastPosts

Jsoup kütühanesinin bize sunduğu en büyük kolaylık burada karşımıza çıkıyor. Bu kısmı görsel üzerindeki açıklamalardan takip edebilirsiniz.

getlastposts

Son aşamada ise gelen verileri listview de gösterebilmek için özel bir adapter yazmamız gerekmektedir. Bu adapter post_row.xml dosyamızı listview’in her bir satırına adapte etmekte aynı zamanda içerisine verilen dataların nasıl konumlanacağını belirlemek için kullanılır.

  • LastPostAdapter.java
public class LastPostsAdapter extends BaseAdapter {
private LayoutInflater myInflater;
 private List<Post> myPosts;
public LastPostsAdapter(Activity activity, List<Post> posts) {
 myInflater = (LayoutInflater) activity
 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 myPosts = posts;
 }
@Override
 public int getCount() {
 return myPosts.size();
 }
@Override
 public Object getItem(int position) {
 return myPosts.get(position);
 }
@Override
 public long getItemId(int position) {
 return position;
 }
@SuppressLint("ViewHolder")
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 View row = null;
 Bitmap bitmap;
 
 row = myInflater.inflate(R.layout.post_row, null);
 
 JustifiedTextView content = (JustifiedTextView)row.findViewById(R.id.txtContent);
 TextView title = (TextView)row.findViewById(R.id.txtTitle);
 TextView address = (TextView)row.findViewById(R.id.txtAddress);
 //TextView content = (TextView)row.findViewById(R.id.txtContent);
 ImageView image = (ImageView)row.findViewById(R.id.imagePost);
 
 content.setAlignment(Align.LEFT);
 title.setText(myPosts.get(position).getTitle());
 address.setText(myPosts.get(position).getAddress());
 content.setText(myPosts.get(position).getShortContent());
 image.setImageBitmap(myPosts.get(position).getImage()); 
 return row;
 }
}

 

Screenshot_2015-03-13-00-23-12

Son olarak MainActivity içerisinde listview’e bu adapteri bağlamamız gerekiyor. Bu işlemi de aşağıda görüldüğü gibi tamamladıktan sonra projemiz tamamlanmış olmaktadır. Projenin çalışan hali şekildeki gibidir. Projenin kaynak kodları için ogzhnozdmr@gmail.com adresine mail atmanız yeterlidir. İyi çalışmalar.

LastPostsAdapter adapter = new LastPostsAdapter(MainActivity.this, lastPosts);
  lastPostsList.setAdapter(adapter);

 

 

4 Comments

Add a Comment

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir