Merhaba arkadaşlar, Bugün sizlere Jsoup kütüphanesi kullanımı ile HTML parse işleminin nasıl gerçekleştirileceğini anlatacağım. HTML Parse , HTML ayrıştırma anlamına gelmektedir. Herhangi bir Html sayfasından istediğimiz yerleri alabilir ve uygulamalarımızda kullanabiliriz. Örneğin web sitemizi , mobil uygulamaya dönüştürmek istiyoruz diyelim; web sitemizin html sayfasında bulunan tag leri ayrıştırarak verileri elde ederiz, bunu da uygulamamızda şekillendiririz.
Jsoup ise Java programlama diline ait açık kaynak kodlu html parser kütüphanesidir. Html element lerine ulaşmamız için bu kütüphaneyi kullanacağız , bu kütüphaneyi kullanabilmek için de projemize import etmemiz gerekiyor.
http://www.mobilhanem.com sitemizden bir kaç veri çekip uygulamamızda gösterelim Android Studio yu açıyoruz Gradle Scripts segmesinden build.gradle a aşağıdaki kodu yapıştırıyoruz, yapıştırdıktan sonra uygulamanızı Rebuild project yapmayı unutmayın. Android Studio arka planda derleme işlemlerini tamamladıktan sonra artık Jsoup kütüphanemizi kullanabilir duruma geleceğiz.
compile 'org.jsoup:jsoup:1.7.3'
Az çok web sayfası kavramından anlayanlarımız bilir ki html tag larını oluştururken id ler kullanabiliriz yada class tag ı vererek onun içinde şekillendirmeler yapabiliriz. Jsoup kütüphanesinin mantığı ise , istenilen url ye bağlantıyı gerçekleştirip , select komutu ile html tag lerine ulaşarak verileri elde etmemizi sağlamaktır. Internet üzerinden bu verilere ulaşmak istediğimiz için Async Task yapısını kullanacağız. Nasıl Json Parse işlemlerinde bu yapıyı kullanıyorsak, Html Parse yaparken de bu yapıyı kullanmamız doğru olacaktır.
url ye bağlantıyı şu şekilde sağlayacağız.
Document doc = Jsoup.connect(URL).get();
URL yazan kısma ulaşmak istediğimiz web sayfasının linkini vermemiz yeterli.
Daha sonra Html elemanlarına ulaşabilmek için belli başlı select komutları var onlardan ihtiyacımız olanları kullanacağız. Daha detaylı komutlara bakmak için tıklayınız.
html <div id=”yourDivName”> tag lerine ulaşabilmek için “#” kullanarak aşağıdaki gibi yazıyoruz.
Elements info = doc.select("div#yourDivName"); Elements info = doc.select("div[id=yourDivName"); // alternatif olarak bunuda kullanabilirsiniz.
html <div class=”yourClassName”> tagıne ulaşabilmek için “.” kullanarak aşağıdaki gibi yazıyoruz.
Elements info = doc.select("div.yourClassName"); Elements info = doc.select("div[class=yourClassName"); // alternatif olarak bunuda kullanabilirsiniz.
Yayınlamış olduğum Parse SDK ile Anlık Bildirim dersi sayfasından verileri çekeceğiz. Burada yer alan site başlığını , açıklamasını ve sitemizin logosunu çekmeye çalışalım. Uygulamamızda 4 adet buton bulunuyor. Bu butonların ne işe yaradığını kaynak kodların içinde yorum olarak belirttim.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <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" tools:context=".MainActivity"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/linearLayout"> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Başlık Göster" android:id="@+id/buttonTitle" /> <LinearLayout android:visibility="gone" android:id="@+id/title_layout" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:textStyle="bold" android:id="@+id/txt_title" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Açıklama Göster" android:id="@+id/buttonDesc" /> <LinearLayout android:visibility="gone" android:id="@+id/desc_layout" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:textStyle="bold" android:id="@+id/txt_desc" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Logo Göster" android:id="@+id/buttonImage" /> <LinearLayout android:visibility="gone" android:id="@+id/logo_layout" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:background="#0000ff" android:id="@+id/img_logo" android:layout_width="fill_parent" android:layout_height="100dp" /> </LinearLayout> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Yazarlar Göster" android:id="@+id/buttonYazarlar" /> <LinearLayout android:visibility="gone" android:id="@+id/yazarlar_layout" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:textStyle="bold" android:id="@+id/txt_yazarlar" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> </RelativeLayout>
MainAcitivity sınıfımız aşağıdadır.
MainActivity.java
package com.mobilhanem.htmlparsingandroid; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.InputStream; public class MainActivity extends Activity { private Button titleButton, descButton, logoButton, yazarlarButton; LinearLayout title_layout, desc_layout, logo_layout, yazarlar_layout; private ProgressDialog progressDialog; private static String URL = "http://www.mobilhanem.com/parse-sdk-ile-anlik-bildirim-gonderme-push-notification/"; private static String baseUrl = "http://www.mobilhanem.com/"; private static String authorUrl = "http://www.mobilhanem.com/yazarlar/"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); titleButton = (Button)findViewById(R.id.buttonTitle); descButton = (Button)findViewById(R.id.buttonDesc); logoButton = (Button)findViewById(R.id.buttonImage); yazarlarButton = (Button)findViewById(R.id.buttonYazarlar); titleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new FetchTitle().execute(); // başlık çekmek için } }); descButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new FetchDescription().execute(); // açıklama çekmek için } }); logoButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new FetchImageLogo().execute(); // logo çekmek için } }); yazarlarButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new FetchYazarlar().execute(); // yazarlar kısmını çekmek için } }); } private class FetchTitle extends AsyncTask<Void, Void, Void> { String title; @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("BAŞLIK"); progressDialog.setMessage("Başlık Çekiliyor..."); progressDialog.setIndeterminate(false); progressDialog.show(); } @Override protected Void doInBackground(Void... params) { try{ Document doc = Jsoup.connect(URL).get(); // web siteye bağlantıyı gerçeleştirme title = doc.title(); // ilgili sayfanın başlığını almak için }catch (Exception e){ e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { title_layout = (LinearLayout)findViewById(R.id.title_layout); TextView txt_title = (TextView)findViewById(R.id.txt_title); title_layout.setVisibility(View.VISIBLE); txt_title.setText("Title: " + "" + title); progressDialog.dismiss(); } } private class FetchDescription extends AsyncTask<Void, Void, Void> { String desc; @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("AÇIKLAMA"); progressDialog.setMessage("Açıklama Çekiliyor..."); progressDialog.setIndeterminate(false); progressDialog.show(); } @Override protected Void doInBackground(Void... params) { try{ Document doc = Jsoup.connect(URL).get(); Elements elements = doc.select("meta[name=description]"); // ilgili sayfanın açıklamasını almak için desc = elements.attr("content"); }catch (Exception e){ e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { desc_layout = (LinearLayout)findViewById(R.id.desc_layout); TextView txt_desc = (TextView)findViewById(R.id.txt_desc); desc_layout.setVisibility(View.VISIBLE); txt_desc.setText("Description: " + "" + desc); progressDialog.dismiss(); } } private class FetchImageLogo extends AsyncTask<Void, Void, Void> { Bitmap bitmap; @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("LOGO"); progressDialog.setMessage("Logo Çekiliyor..."); progressDialog.setIndeterminate(false); progressDialog.show(); } @Override protected Void doInBackground(Void... params) { try{ Document doc = Jsoup.connect(baseUrl).get(); Elements elements = doc.select("img[src]"); String imgSrc = elements.attr("src"); InputStream input = new java.net.URL(imgSrc).openStream(); bitmap = BitmapFactory.decodeStream(input); }catch (Exception e){ e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { logo_layout = (LinearLayout)findViewById(R.id.logo_layout); ImageView img_logo = (ImageView)findViewById(R.id.img_logo); logo_layout.setVisibility(View.VISIBLE); img_logo.setImageBitmap(bitmap); progressDialog.dismiss(); } } private class FetchYazarlar extends AsyncTask<Void, Void, Void> { String authors; @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("YAZARLAR"); progressDialog.setMessage("Yazarlar Çekiliyor..."); progressDialog.setIndeterminate(false); progressDialog.show(); } @Override protected Void doInBackground(Void... params) { try{ Document doc = Jsoup.connect(authorUrl).get(); Elements elements = doc.select("div[class=post-content]"); // class ismi post-content olan verileri çekmek için authors = elements.text(); }catch (Exception e){ e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { yazarlar_layout = (LinearLayout)findViewById(R.id.yazarlar_layout); TextView txt_yazarlar = (TextView)findViewById(R.id.txt_yazarlar); yazarlar_layout.setVisibility(View.VISIBLE); txt_yazarlar.setText(authors); progressDialog.dismiss(); } } }
Android Jsoup ile HTML Parsing
MainActivity sınıfımızda yer alan kodları incelemeye başlayalım. Uygulamayı çalıştırdığınız zaman göreceksiniz ki ilk butona tıklandığı an ilgili sayfanın başlığını çekip ekrana yazdırıyoruz. Bunu FetchTitle ismini verdiğim methodu incelersek eğer Async Task yapısında bildiğiniz üzere ilk olarak onPreExecute methodu çalışıyor orada kullanıcıya mesajı gösteriyoruz ve hemen ardından çalışan doInBackground methodu ile ilgili url ye bağlanıyoruz. ( http://www.mobilhanem.com/parse-sdk-ile-anlik-bildirim-gonderme-push-notification/ ) bu sayfamızda çekmeye çalıştığımız başlık kısmına sayfanın source-code nu görüntüleyerek bakarsak eğer ; resimde de görüldüğü gibi title kısmında yer alan yazıyı onPostExecute methodunda TextView e yazdırdık.
İkinci butona tıklandığı zaman ise FetchDescription isimli method çalışarak; ilgili sayfanın açıklaması çekilip ekrana yazdırılıyor. Yukarıda anlatmış olduğum yapı burası içinde geçerli bu yüzden tekrardan aynı şeylerden bahsetmeyeceğim. meta tagında yer alan description un content değişkenine ulaştıktan sonra bunu TextView e yazdırıyoruz. Bu veriyi çektiğimiz ilgili sayfanın html görüntüsüne bakacak olursak ;
Üçüncü butona tıklandığı zaman ise FetchImageLogo isimli method çalışarak; ilgili sayfanın logo su çekilip ekranda gösteriliyor. Bu dersimizin kaynak kodunu incelerseniz eğer, başka bir url segmesine bağlantıyı gerçekleştirdiğimi göreceksiniz. Burada ilgili web sayfalarının farklı kısımlarına da ulaşabileceğimizi göstermek istedim. Sayfanın logo sunu çekerken img[src] ifadesini kullandığımı göreceksiniz burada sayfanın kaynak resim dosyasını çekebilmemiz için gerekli olan bu kodu kullanarak, çekilen veriyi önce Bitmap e çevirip daha sonra ImageView e set ettik. Logo yu çektiğimiz ilgili sayfanın html görüntüsüne bakacak olursak ;
ve son olarak dördüncü butona basıldığında FetchYazarlar methodunu çağırdık burada yine ilgili web sitesinin başka bir sayfasına bağlantıyı gerçekleştirdik ve yazarlar bölümünü çekip ekrana yazdırdık. Zaten bağlantıyı kurduğumuz url yi görüntüleyecek olursanız class adının post-content verildiğini göreceksiniz, div[class=post-content] komutunu kullanarak gerekli işlemleri gerçekleştirdik. Yazarlar kısmını çektiğimiz ilgili sayfanın html görüntüsüne bakacak olursak ;
Html parse nasıl yapılır böylece sizlere göstermiş oldum, gerçekten çok kullanışlı ve biraz html bilginiz var ise bunu Android ile birleştirip işinize yarayabilecek işlemleri kolayca gerçekleştirebilirsiniz. Jsoup mantığını ilerletmek istiyorsanız eğer uygulamalarınızda kullanmadan önce online-tool kullanarak alıştırmalar yapabilirsiniz. ( http://try.jsoup.org/~iayWCMYVlvXEUrAws7ziRaMU3bM ) Kullanmak istediğiniz web sayfasına gelip sağ tıklayarak Inspect Element deyin ve html kodlarını seçip bu online-tool a yapıştırın. Daha sonrasında Jsoup daki Select komutlarını kullanmaya çalışın gerçekten çok işinize yaradığını göreceksiniz.
Tüm Android Ders, Proje ve Kaynak Kodlar için tıklayınız.
Ders hakkında soru ve önerilerinizi çekinmeden yorum bırakabilirsiniz. Bol Android’li günler sizin olsun
Sizlerden ricamız facebook.com/mobilhanem sayfamızı beğenmenizdir. Diğer dersimde görüşmek üzere kendinize iyi bakın..
uzun bir aradan sonra yeni ders eklenmiş. gerçekten faydalı bir yazı olmuş teşekkürler
yorum için teşekkür ederim bundan sonra yeni dersler yayınlamaya devam edeceğiz.
güzel makale, teşekkürler.
çok saolun, iyi çalışmalar
[…] kütüphanesini kullanma ve ne işe yaradığı ile ilgili ayrıntılı dersimizi buradan […]
Merhaba Alper Hocam,
Jsoup ile bir html elementini başka bir element ile değiştirme işini nasıl yapabiliriz?
merhaba hocam benim bir uyglama oluşturdm webview birkaç menü ekledim fakat webview sayfa kaynak kodunu view-source kodlarını göstermiyor.aslında yapmak istedigim şu webviev da herhangi bir linkle tıklandıgında o linki otomatik kopyalamak yardımcı olursanız sevinirim.
yanlı resmi yükledim özür diliyorum bu hatayı çözmüştüm.
merhaba hocam Document doc değeri debug esnasında sürekli null dönüyor bunun sebebi ne bir çözüm bulamadım cevaplarsanız sevinirim
bu dersin kaynak kodlarını indirip denediğinizde mi null geliyor ? null gelmemesi lazım bu yazdığım derste verileri düzgün basıyor ekrana. internet ayarları yada verdiğiniz url yi kontrol eder misiniz
Manifest dosyasında internet erişimi izni vermelisiniz
Merhaba sizin jsoup dersinizi inceledim elinize sağlıkyalnız form elementi nasıl çekilir bulamadım. textbox button filan yardımcı olabilir misiniz ?
merhabalar, formElement.select(“input[name=id]”).first() bu yapıda bir kod kullanmanız gerekmektedir form elementini çekebilmeniz için
yukarıdaki örnek yapıya baktığımızda formElement.attr(“action”) dediğimizde deneme.php yı getirmesi gerekiyor. Verdiğim örnekleri dener misiniz ayrıca daha detaylı bilgi edinmek istersen jsoupun kendi sitesini incelemeni tavsiye ederim. ( http://jsoup.org/cookbook/extracting-data/dom-navigation )
HTML sayfasında birden çok title etiketine sahip veri varsa eğer, bu
durumda Android uygulaması HTML sayfasındaki tüm title içeriklerini mi
alıyor yoksa sadece HTML sayfasında ilk önce title etiketinin içeriğini
alıp, diğerlerini almıyor mu? Bu sorunun cevabına ciddi anlamda çok
ihtiyacım var.
Merhabalar,
Document doc = Jsoup.connect(URL).get();
title = doc.title(); // burada url sini verdiğiniz ilgili web sayfasının başlığı ne ise onu alıyoruz bütün hepsini çekmiyor
resimleri çekmiyo yukarda gösterilen gibi yaptım ama olmuyo bi yardımcı olursanız sevinirim
Merhaba, ilgili kaynak kodu indirip denediniz mi ? bu derste kullanılan url lere dikkat et farklı bir url de işlem yapıyorsan o zaman işler değişir..
Bi tek gosterimde sıkıntı cıkarıyor url felan alıyor ama gostermiyor baska kodu varmı aceba
bunu ekledin mi manifest e?
resimleri göstermesi için picasso kullanabilirsin.
S.a
Anlatım için teşekkür ederim çok yardımcı oldu.
Bir sorum olacaktı;
ben logo çeker gibi yüklenen sayfanın içindeki linkleri almak istiyorum.
bunun için ;
Elements elements = doc.select(“a[href]”);
title = elements.attr(“href”);
şeklinde kullandım ve sayfanın içindeki ilk linki alıyorum fakat bütün linkleri almak için döngü içine almam gerek .Sayfa içindeki bütün linkleri alıp istediğim link adresini bulunca click yaptırtmak istiyorum yardımcı olabilirmisiniz ?
Şimdiden teşekkür ederim.İyi çalışmalar.
Merhabalar, Ben wp sitenin belli bir tag aralığını resimleriyle birlikte css kodları ve javascript kodları çalışacak şekilde nasıl çekebilirim ?
Hızlı çekmek için en iyi yöntem nedir. Teşekkür ederim
Yukarıdaki ders zaten bunu anlatıyor. Sitenn wp olması farketmez.
Siz beni anlamadınız sanırım. Tmm yukardaki örnek de bunu anlatıyor ama şöyle bir durum var; Ben belirttiğim tag arasındaki sadece yazıyı veya sadece resimi almak yerine ikisini de aynı anda almak istiyorum. Mesela div class.haberler olan taglarımı bir döngü yardımıyla kaç haber varsa o haberler hakkında tüm veriyi çekmek istiyorum ama bazılarında video olabilir olmayabilir de. Bunu nasıl ayarlayabilirim? Anlatabildim mi?
Merhabalar, kaynak kodlarını almak istediğim site girişte şifre ile destekli , bu şifre alanını nasıl doldurup asıl sayfa kaynak dosyasına ulaşabilirim yardımcı olursanız çok sevinirim..
neden paylaşımların sonuna ss koymuyorsunuz çok daha etkili içerik olur.
Evet haklısın yeni derslerimizde çalışan hallerinin videolarını koymaya çalışıyoruz. Teşekkürler.
internet bağlantısının olmadığı lokal netwroklerde kullanabiliyor muyuz jsoup u ? Çekeceğim veri tamamen xml’den oluşmakta. Jsoup internet bağlantısı olmayan local networklerde kullanılamıyorsa, başka bir tavsiyeniz var mı?
Merhaba ne yazık ki kullanamazsınız internet bağlantısı olması gerekiyor. burada da sizin sorduğunuz soruyu sormuşlar incelemeniz faydalı olacaktır.
Size sorduktan sonra denedim, internet bağlantısı olmadan da çekti. Ama Siz böyle cevap verince bi şaşırdım. Neden çektiğini araştırıyorum şuan =)
Ben Sitedeki dersleri çekmek istiyorum ve dersler video direk videonun başka bir pencere açmadan aynı pencerede izlemesini istiyorum bunu nasıl yapa bilirim lütfen yardımcı olurmusunuz
Select Methodunun kırmızı olmasının sebebi nedir sizce ? https://uploads.disquscdn.com/images/8f3421953b2caac4aa9e082155bd8c9600291b19826d36fe6010810c734d44c8.png
Hocam çok iyi anlatım teşekkür ederim. Peki login yapılması gereken sayfalarda ne yapmamız gerekiyor ?
merhaba ,genelde parse işlemlerinde web servis yazılıyormuş.Biarkaç araştırmama göre json formatında veriler çekiliyormuş.örneğin bir yemek listesini çekmek istiyorum .ama json formatında değil.ne yapmam lazım ?ikinci olarak json dosyasını sunucuda barındırmak gerekiyomuş.İlla bir sunucu mu kiralamam lazım en basit işler için biler ?
Teşekkürler,mükemmel.
Mevcut kodları keşke tamamen güncelleniz değişiklik yapmadan çalışmaz büyük bir ihtimal
merhaba, buradaki kodları indirip android studio da çalıştırmayı denediniz mi ?
Merhaba, javascript kullanan sitelerden veri gelmiyor.Bununla ilgili bir bilginiz varmı.
thanks it helps a lot. uzun bir aradan sonra yeni ders eklenmiş. gerçekten faydalı bir yazı olmuş teşekkürler