Reyza

tenang, senang, sederhana
See also: Other Geeks@INDC

Public

Screen Scraping : “Mencuri” Data Website dengan Elegan

Pada sebuah event komunitas gw mendengar istilah “mencuri” dari untuk menggantikan kata kerja “mengambil” data pada suatu site di internet.  Seperti “mencuri” pada umumnya ada dua cara yang bisa digunakan, yaitu :

1. Dengan Otot.

2. Dengan Otak.

Di internet kita dapat melihat data dapat diakses dengan mudah dengan browser, dan berikut ini contoh data yang mungkin kita lihat.

image

Atau seperti berikut :

image

Untuk aksi pencurian dengan otot maka langkahnya sangat gampang, cukup lakukan aksi blok data kemudian copy dan paste ke tempat yang diinginkan. Misalnya pada notepad, kemudian masih dengan bantuan otot, lakukan pembersihan data untuk mengambil item-item yang diperlukan. Misal pada contoh gambar di atas, item yang penting untuk diambil seperti RCTI, 01 Juni 2011 dan nama acara TV dan jam tayangnya. Sedangkan pada data gambar di atas, maka yang diperlukan selain data yang berhubungan dengan gambar juga gambarnya sendiri. Untuk mendapatkan gambarnya maka cukup perintahkan otot untuk melakukan aksi klik kanan dan save as image bersangkutan, satu per satu :)  Setelah data tersebut di dapatkan maka tinggal lakukan yg diinginkan, masih menggunakan otot, mungkin bisa dilanjutkan dengan menyalin data tersebut ke database.

Kalau otot-otot telah cape, maka bisa dipikirkan untuk mencuri dengan cara yang lebih elegan dan dan otot tidak perlu digunakan lagi (agar kalori tetap stabil dan gemuk tetap bertahan).  Salah satu caranya adalah dengan melakukan Screen Scraping.

Screen Scraping, apa sih itu?

Mungkin paparan ini akan “sedikit” menjawab. Sebagai contoh data dari acara TV di atas tidak lain adalah bagian dari sebuah halaman HTML, dan kira-kira berikut adalah kode HTML dari potongan data di atas.

   1: <div class='post' id='post'>
   2: <a name='4306621538310684552'></a>
   3: <h2 class='title'>
   4: <a href='http://www.televisi-indonesia.com/2011/06/rcti-rabu-01-juni-2011.html'>RCTI, Rabu 01 Juni 2011</a>
   5: </h2>
   6: <div class='post-date'>
   7: <p>
   8: </p>
   9: </div>
  10: <div class='post-info clearfix'>
  11: <p class='author alignleft'>
  12: Posted by
  13:  
  14: <span class='fn'>akbarri</span>
  15: </p>
  16: <p class='comments alignright'>
  17: <a class='comments' href='http://www.televisi-indonesia.com/2011/06/rcti-rabu-01-juni-2011.html#comments' onclick=''>0
  18: comments</a>
  19: </p>
  20: </div>
  21: <div class='post-content clearfix'>
  22: <p>
  23: 00:30 - 02:30 BOM:POLICE STORY 4<br />
  24: 02:30 - 03:00 SEPUTAR INDONESIA MALAM<br />
  25: 03:00 - 04:00 HIGHLIGHT UEFA CHAMPIONS LEAGUE<br />
  26: 04:00 - 04:30 ASSALAMU'ALAIKUM USTADZ<br />
  27: 04:30 - 06:00 SEPUTAR INDONESIA PAGI<br />
  28: 06:00 - 07:30 GO SPOT<br />07:30 - 11:00 DAHSYAT<br />
  29: 11:00 - 12:00 INFOTAINMENT INTENS<br />
  30: 12:00 - 12:30 SEPUTAR INDONESIA SIANG<br />
  31: 12:30 - 13:00 SEPUTAR PERISTIWA<br />
  32: 13:00 - 15:00 SINEMA SIANG: CINTA HIGIENIS<br />
  33: 15:00 - 16:00 CEK & RICEK<br />
  34: 16:00 - 17:00 BEDAH RUMAH<br />
  35: 17:00 - 17:30 SEPUTAR INDONESIA<br />
  36: 17:30 - 18:30 SILET<br />
  37: 18:30 - 19:30 MEGA SINETRON:PUTRI YANG DITUKAR<br />
  38: 19:30 - 21:00 MEGA SINETRON: ANUGERAH<br />
  39: 21:00 - 22:30 MEGA SINETRON : KASIH DAN CINTA<br />
  40: 22:30 - 00:30 MEGA SINEMA : PENGAMEN CINTA KACANGAN
  41: <div style='clear: both;'></div>
  42: </p>
  43: </div>

Dapat dilihat bawah data berada di dalam tag div dengan atribut class= post dan id=post yang terlihat pada baris ke-1 dan di akhiri pada baris ke-42. Sedangkan pada baris ke-3 sampai baris ke-5 dapat dilihat title dari data tersebut yang berisi “RCTI, Rabu 01 Juni 2011”. Sedangkan data acara TV-nya berada diantara tag div dengan atribut class=’post-content clearfix’.

Nah salah satu dari banyak aksi Screen Scraping adalah mengambil data berdasarkan tag HTML dengan aturan sesuai identitas yang telah disebutkan di atas atau yang diinginkan.  Atribut seperti nama pada atribut class atau pada atribut id dapat dijadikan penanda untuk menemukan data yang diinginkan.

Jadi bisa diartikan Screen Scraping adalah teknik yang dapat digunakan untuk “mengekstrak” data yang diinginkan pada suatu halaman web (HTML), walau tentunya ada fungsi lain dari Screen Scraping. CMIIW.

Di posting ini akan dicoba melakuan Screen Scraping dengan class library yang sudah ada dan menampilkan hasilnya pada suatu halaman web yang akan kita buat sendiri. Class library yang akan digunakan adalah Html Agility Pack yang dapat ditemui disini http://htmlagilitypack.codeplex.com. Setelah HtmlAgilityPack.1.4.0.zip diekstrak maka akan ditemui tiga file berikut.

image

Sekarang cukup lakukan penyalinan file .dll dan .xml ke folder Bin pada Web Site Project seperti berikut :

image

Pada gambar di atas dapat dilihat kedua file tersebut berada pada project AcaraTV.

Selanjutnya akan kita buat sebuah halaman untuk mengambil 1 posting yang ada disuatu web yg berisi daftar acara TV. Berikut kira-kira contoh yang dapat kita tulis.

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title></title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <div>
  12:         <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
  13:     </div>
  14:     </form>
  15: </body>
  16: </html>

Pada baris ke-12 dapat dilihat terdapat kontrol Label yang akan digunakan untuk menampilkan data curian ini :)

Dan pada file Default.aspx.cs

   1: using System;
   2:  
   3: using HtmlAgilityPack;
   4:  
   5: public partial class _Default : System.Web.UI.Page
   6: {
   7:     protected void Page_Load(object sender, EventArgs e)
   8:     {
   9:         HtmlWeb web = new HtmlWeb();
  10:         HtmlDocument doc = web.Load("http://www.televisi-indonesia.com");
  11:         var name = doc.DocumentNode.SelectSingleNode("//div[@id='post']").InnerHtml;
  12:         Label1.Text = name;
  13:     }
  14: }

Pada baris ke-3 dapat dilihat pendaftaran namespace HtmlAgilityPack agar class-class didalamnya dapat digunakan.  Class dari namespace ini yang digunakan adalah HtmlWeb dan HtmlDocument. Pada baris ke-10 dapat dilihat bagaimana cara untuk “menunjuk” site atau page sebagai rumah target pencurian. Sedangkan pada baris-11 adalah cara untuk melakukan pencurian barang yang diinginkan, dapat dilihat bagaimana cara menunjuk area div dengan atribut id=post di baris ini. Selanjutnya pada baris ke-12 cara paling sederhana untuk menampilkan hasil curian :)

Kira-kira berikut hasilnya.

image

Hm, terlihat masih “kotor” karena terdapat “link-link” yang tidak enak dipandang mata dan tidak diperlukan. Kita akan coba untuk mengambil “RCTI, Kamis 02 Juni 2011” saja tanpa bisa dilik dan data jadwal acara saja. Untuk itu maka gw akan coba ganti beberapa baris kode sebelumnya dengan seperti di bawah ini.

   1: <asp:Label ID="Label_StasiunTV" runat="server" Text="Label"></asp:Label>
   2: <br />
   3: <asp:Label ID="Label_DaftarAcara" runat="server" Text="Label"></asp:Label>

Untuk mengisi kedua kontrol tersebut maka dapat dilakukan dengan cara berikut.

   1: using System;
   2:  
   3: using HtmlAgilityPack;
   4:  
   5: public partial class _Default : System.Web.UI.Page
   6: {
   7:     protected void Page_Load(object sender, EventArgs e)
   8:     {
   9:         HtmlWeb web = new HtmlWeb();
  10:         HtmlDocument doc = web.Load("http://www.televisi-indonesia.com");
  11:         var stasiunTV = doc.DocumentNode.SelectSingleNode("//div[@id='post']//h2[@class='title']//a").InnerHtml;
  12:         var daftarAcara = doc.DocumentNode.SelectSingleNode("//div[@id='post']//div[@class='post-content clearfix']//p").InnerHtml;
  13:  
  14:         Label_StasiunTV.Text = stasiunTV;
  15:         Label_DaftarAcara.Text = daftarAcara;
  16:     }
  17: }

Dan berikut hasilnya :

image

Aaah lumayan rapi sekarang. Pada baris ke-11 kita dapati pola seperti berikut “//div[@id='post']//h2[@class='title']//a” yang artinya kira akan mengambil sesuatu yang berada pada :

1. Diantara tag a (<a>…</a>)

2. Dimana tag a tersebut berada di dalam tag h2 dengan atribut class=title (<h2 class=’title’><a>…</a></h2>).

3. Yang mana tag h2 tersebut berada di dalam tag div dengan atribut id=post (<div id=’post’><h2 class=’title’><a>…</a></h2></div>).

Begitu juga untuk baris ke-12.

Kalau di atas dicontohkan hanya berfungsi untuk mengambil 1 item pada 1 area saja, sekarang kita akan coba untuk mengambil lebih dari 1 item pada area yang mempunyai pola yang sama.  Perlu diketahui bahwa pada halaman site tersebut tidak hanya ada data jadwal dari stasiun RCTI saja tapi juga ada dari stasiun lain.  Dan setiap data dari stasiun lain tersebut ditulis dengan cara yang sama seperti data pada stasiun RCTI.

Berikut adalah halaman dari website yang menampilkan jadwal TV di Indonesia.

image

Contoh berikut akan menampilkan daftar stasiun TV, yang didapat dari title pada posting di web tersebut.  Daftar stasiun TV ini nanti akan ditampilkan pada kontrol DropDownList. Berikut contoh kode-nya.

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="StasiunTV.aspx.cs" Inherits="StasiunTV" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title></title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <div>
  12:         <asp:DropDownList ID="DropDownList_StasinTV" runat="server">
  13:         </asp:DropDownList>
  14:     </div>
  15:     </form>
  16: </body>
  17: </html>

Dan berikut.

   1: using System;
   2: using System.Web.UI.WebControls;
   3:  
   4: using HtmlAgilityPack;
   5:  
   6: public partial class StasiunTV : System.Web.UI.Page
   7: {
   8:     protected void Page_Load(object sender, EventArgs e)
   9:     {
  10:         HtmlWeb web = new HtmlWeb();
  11:         HtmlDocument doc = web.Load("http://www.televisi-indonesia.com");
  12:         var stasiunTVs = doc.DocumentNode.SelectNodes("//div[@id='post']//h2[@class='title']//a");
  13:  
  14:         if (stasiunTVs != null)
  15:         {
  16:             ListItemCollection items = new ListItemCollection();
  17:  
  18:             foreach (var stasiunTv in stasiunTVs)
  19:             {
  20:                 string[] stasiunTVArr = stasiunTv.InnerText.Split(',');
  21:  
  22:                 ListItem item = new ListItem();
  23:                 item.Text = stasiunTVArr[0];
  24:                 item.Value = stasiunTVArr[0];
  25:                 items.Add(item);
  26:             }
  27:  
  28:             DropDownList_StasinTV.DataSource = items;
  29:             DropDownList_StasinTV.DataTextField = "Text";
  30:             DropDownList_StasinTV.DataValueField = "Value";
  31:             DropDownList_StasinTV.DataBind();
  32:         }
  33:     }
  34: }

Perbedaan dengan contoh sebelumnya adalah pada baris ke-12. Disini kita gunakan method SelectNodes untuk mengambil koleksi dari node yang ditentukan.  Dengan begitu kita dapat “mencuri” banyak item sekaligus dengan sekali tepukan :) Setelah itu hasilnya akan ditampung pada ListItemCollection yang nanti akan di-bind ke DropDownList. Hasilnya bisa dilihat seperti gambar berikut ini.

image

Contoh selanjutnya adalah akan menampilkan daftar jadwal acara berdasarkan stasiun TV yang dipilih. Jadwal acara akan ditampilkan pada kontrol GridView. Berikut kodenya.

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="StasiunTV.aspx.cs" Inherits="StasiunTV" %>
   2:  
   3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   4:  
   5: <html xmlns="http://www.w3.org/1999/xhtml">
   6: <head runat="server">
   7:     <title></title>
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <asp:ScriptManager ID="ScriptManager1" runat="server">
  12:     </asp:ScriptManager>
  13:     <asp:UpdatePanel ID="UpdatePanel1" runat="server">
  14:         <ContentTemplate>
  15:             <div>
  16:                 Pilih Stasiun TV :
  17:                 <asp:DropDownList ID="DropDownList_StasinTV" runat="server" AutoPostBack="True" onselectedindexchanged="DropDownList_StasinTV_SelectedIndexChanged">
  18:                 </asp:DropDownList>
  19:                 <asp:UpdateProgress ID="UpdateProgress1" runat="server">
  20:                 <ProgressTemplate>Sedang mengambil data...</ProgressTemplate>
  21:                 </asp:UpdateProgress>
  22:             </div>
  23:             <br />
  24:             <div>
  25:                 <asp:GridView ID="GridView_Jadwal" runat="server">
  26:                 </asp:GridView>
  27:             </div>
  28:         </ContentTemplate>
  29:     </asp:UpdatePanel>
  30:     </form>
  31: </body>
  32: </html>

Dan ini :

   1: using System;
   2: using System.Web.UI.WebControls;
   3:  
   4: using HtmlAgilityPack;
   5: using System.Collections;
   6:  
   7: public partial class StasiunTV : System.Web.UI.Page
   8: {
   9:     protected void Page_Load(object sender, EventArgs e)
  10:     {
  11:         if (!IsPostBack)
  12:         {
  13:             DropDownList_StasiunTV_DataBind();
  14:             GetJadwalTVFromWeb();
  15:         }
  16:     }
  17:  
  18:     protected void GetJadwalTVFromWeb()
  19:     {
  20:         HtmlWeb web = new HtmlWeb();
  21:         HtmlDocument doc = web.Load("http://www.televisi-indonesia.com");
  22:         var data = doc.DocumentNode.SelectNodes("//div[@id='post']");
  23:  
  24:         if (data != null)
  25:         {
  26:             IList jadwalList = new ArrayList();
  27:  
  28:             foreach (var item in data)
  29:             {
  30:                 string[] stasiun = item.SelectSingleNode("h2[@class='title']//a").InnerText.Split(',');
  31:  
  32:                 if (stasiun[0].Equals(DropDownList_StasinTV.SelectedValue))
  33:                 {
  34:                     string[] dataJadwal = item.SelectSingleNode("div[@class='post-content clearfix']//p").InnerHtml.Replace("<br>", "#").Split('#');
  35:  
  36:                     foreach (var jadwal in dataJadwal)
  37:                     {
  38:                         JadwalTV jadwalTV = new JadwalTV();
  39:                         jadwalTV.Stasiun = stasiun[0];
  40:                         jadwalTV.Waktu = jadwal.Substring(0, 14);
  41:                         jadwalTV.NamaAcara = jadwal.Substring(14);
  42:                         jadwalList.Add(jadwalTV);
  43:                     }
  44:                 }
  45:             }
  46:  
  47:             GridView_Jadwal.DataSource = jadwalList;
  48:             GridView_Jadwal.DataBind();
  49:         }
  50:     }
  51:  
  52:     protected void DropDownList_StasiunTV_DataBind()
  53:     {
  54:         HtmlWeb web = new HtmlWeb();
  55:         HtmlDocument doc = web.Load("http://www.televisi-indonesia.com");
  56:         var stasiunTVs = doc.DocumentNode.SelectNodes("//div[@id='post']//h2[@class='title']//a");
  57:  
  58:         if (stasiunTVs != null)
  59:         {
  60:             ListItemCollection items = new ListItemCollection();
  61:  
  62:             foreach (var stasiunTv in stasiunTVs)
  63:             {
  64:                 string[] stasiunTVArr = stasiunTv.InnerText.Split(',');
  65:  
  66:                 ListItem item = new ListItem();
  67:                 item.Text = stasiunTVArr[0];
  68:                 item.Value = stasiunTVArr[0];
  69:                 items.Add(item);
  70:             }
  71:  
  72:             DropDownList_StasinTV.DataSource = items;
  73:             DropDownList_StasinTV.DataTextField = "Text";
  74:             DropDownList_StasinTV.DataValueField = "Value";
  75:             DropDownList_StasinTV.DataBind();
  76:         }
  77:     }
  78:  
  79:     protected void DropDownList_StasinTV_SelectedIndexChanged(object sender, EventArgs e)
  80:     {
  81:         GetJadwalTVFromWeb();
  82:     }
  83: }
  84:  
  85: public class JadwalTV
  86: {
  87:     public string Stasiun { set; get; }
  88:     public string Waktu { set; get; }
  89:     public string NamaAcara { set; get; }
  90: }

Dan berikut hasilnya :

image

Implikasi

Pada paparan di atas hanya mencontohkan bagaimana menggunakan salah satu teknik Screen Scraping untuk mengambil data pada suatu halaman web. Data yang dapat diambil dapat ditampilkan secara langsung seperti cara di atas atau disimpan pada database dan dipublish dengan menggunakan berbagai macam nama seperti Web Service, OData atau WCF Data Service sehingga nanti dapat dikonsumsi dan dimanfaatkan oleh client seperti Silverlight atau Windows Phone 7 bahkan Symbian atau iOS. Bagian ini akan di bahas pada posting berikutnya, dengan implementasi pembuatan aplikasi mobile Jadwal Televisi Indonesia :)

Selamat menikmati liburan panjang, bagi yang mengalaminya.

Share this post: | | | |

Comments

arthspotter said:

nice post ^_^

# June 7, 2011 4:28 PM