Selasa, 20 Februari 2024

Scrape Data dari Website KPU dengan Free Pascal dan Lazarus

Hallo guys,

Jadi ceritanya kemarin saya iseng membuat aplikasi web scraping menggunakan Free Pascal dan IDE Lazarus. Karena kebetulan lagi momen Pemilu 2024, Idenya adalah mengambil data dari website Komisi Pemilihan Umum (KPU) di alamat https://pemilu2024.kpu.go.id/ dengan metode grab alias scraping menggunakan teknik browser automation. Adapun hasil akhirnya adalah memperoleh data hasil perhitungan Pilpres dari tingkat Provinsi - Kabupaten/Kota - Kecamatan - Kelurahan/Desa - TPS. Sekalian kita akan mengambil atau mendownload foto/gambar C1 Plano/Hasil yang ada di TPS tersebut.

Pada contoh ini saya akan mengambil data dari Provinsi NUSA TENGGARA BARAT yang mana alamat URL nya adalah https://pemilu2024.kpu.go.id/pilpres/hitung-suara/52. Dari halaman tersebut kita akan mengambil data Kabupaten/Kota (contoh : KOTA MATARAM), yang selanjutnya akan kita gunakan untuk mendapatkan data Kecamatan (contoh : SELAPARANG) , kemudian kita gunakan untuk mendapatkan data Kelurahan/Desa (contoh : REMBIGA) dan terakhir mendapatkan data TPS (contoh : TPS 002).

Oke, Lets Do It!

Pertama-tama siapkan perkakas yang digunakan. Dalam hal ini adalah WebDriver4L dan Google Chrome Driver (sesuaikan dengan versi yang terpasang di komputer anda)

Kedua, Buat projek menggunakan Lazarus IDE. Saya menggunakan Lazarus versi 2.2.2 dan Free Pascal 3.2.2. Letakan semua file yang ada di WebDriver4L ke dalam folder projek. Berikutnya tambahkan Webdriver4L di uses dan deklarasikan variabel global sbb:

  Robot : TWebDriver;
  kabupaten_kota, kecamatan, kelurahan_desa, tps : TWebElements;
  urlkab, urlkec, urldesa, urltps : String;
  i : integer;

  const
    main_url = 'https://pemilu2024.kpu.go.id';  

Selanjutnya tambahakan Google Chrome Driver yang telah didownload sebelumnya ke dalam folder projek kemudian desain formnya seperti gambar di bawah ini

Tauhidslab

Ketiga, mengambil data Kabupaten dan Kota dari URL Provinsi NUSA TENGGARA BARAT menggunakan script di bawah ini, letakan di dalam tombol Ambil Data Kab/Kota. Sekedar informasi, untuk mendapatkan XPath, klik kanan di browser - Inspect - Klik Kanan di Element - Copy - Copy full XPath.

  {$IFDEF WINDOWS}
  Robot := TChromeDriver.Create(nil);
  Robot.StartDriver(ExtractFileDir(Paramstr(0)) + '\chromedriver.exe');
  {$ELSE}
  //Robot := TChromeDriver.Create(nil);
  Robot := TFireFoxDriver.Create(nil);
  //Robot.StartDriver(ExtractFileDir(Paramstr(0)) + '/chromedriver');
  Robot.StartDriver(ExtractFileDir(Paramstr(0)) + '/geckodriver');
  {$ENDIF}
  Robot.NewSession;
  Robot.Implicitly_Wait(1000);
  Robot.Set_Window_Size(640, 640);
  Robot.GetURL(main_url+'/pilpres/hitung-suara/52');
  Sleep(2000);
  kabupaten_kota := Robot.FindElementsByXPath('//*[@id="main"]/div[3]/div[2]/div[2]/div[2]/div/div/table/tbody/tr/td[1]/a');
  Memo1.Clear;
  Memo1.Append('=== Data Kabupaten/Kota ===');
  for i := 0 to kabupaten_kota.Count - 1 do
  begin
       Memo1.Append(kabupaten_kota.Items[i].Text);
       if (kabupaten_kota.Items[i].Text='KOTA MATARAM') then urlkab:=kabupaten_kota.Items[i].AttributeValue('href');
  end;   

Keempat, mengambil data Kecamatan dari KOTA MATARAM menggunakan script di bawah ini, letakan di dalam tombol Ambil Data Kecamatan

  Robot.GetURL(main_url+urlkab);
  Sleep(2000);
  kecamatan := Robot.FindElementsByXPath('//*[@id="main"]/div[3]/div[2]/div[2]/div[2]/div/div/table/tbody/tr/td[1]/a');
  Memo1.Append('=== Data Kecamatan ===');
  for i := 0 to kecamatan.Count - 1 do
  begin
       Memo1.Append(kecamatan.Items[i].Text);
       if (kecamatan.Items[i].Text='SELAPARANG') then urlkec:=kecamatan.Items[i].AttributeValue('href');
  end;  

Kelima, mengambil data Kelurahan dari Kecamatan SELAPARANG menggunakan script di bawah ini, letakan di dalam tombol Ambil Data Kelurahan/Desa

  Robot.GetURL(main_url+urlkec);
  Sleep(2000);
  kelurahan_desa := Robot.FindElementsByXPath('//*[@id="main"]/div[3]/div[2]/div[2]/div[2]/div/div/table/tbody/tr/td[1]/a');
  Memo1.Append('=== Data Kelurahan/Desa ===');
  for i := 0 to kelurahan_desa.Count - 1 do
  begin
       Memo1.Append(kelurahan_desa.Items[i].Text);
       if (kelurahan_desa.Items[i].Text='REMBIGA') then urldesa:=kelurahan_desa.Items[i].AttributeValue('href');
  end;  

Keenam, mengambil data TPS dari Kelurahan REMBIGA menggunakan script di bawah ini, letakan di dalam tombol Ambil Data TPS

  Robot.GetURL(main_url+urldesa);
  Sleep(2000);
  tps := Robot.FindElementsByXPath('//*[@id="main"]/div[3]/div[2]/div[2]/div[2]/div/div/table/tbody/tr/td[1]/a');
  Memo1.Append('=== Data TPS ===');
  for i := 0 to tps.Count - 1 do
  begin
       Memo1.Append(tps.Items[i].Text);
       if (tps.Items[i].Text='TPS 002') then urltps:=tps.Items[i].AttributeValue('href');
  end;   

Ketujuh, mengambil informasi hasil perhitungan dari data TPS 002 menggunakan script di bawah ini, letakan di dalam tombol Ambil Hasil Perhitungan

var
  anies, prabowo, ganjar : TWebElement;
begin
  Robot.GetURL(main_url+urltps);
  Sleep(2000);
  anies := Robot.FindElementByXPath('/html/body/div/div[1]/div/div[3]/div[2]/div[2]/div/div/div[1]/table[2]/tbody/tr[1]/td[3]');
  prabowo := Robot.FindElementByXPath('/html/body/div/div[1]/div/div[3]/div[2]/div[2]/div/div/div[1]/table[2]/tbody/tr[2]/td[3]');
  ganjar := Robot.FindElementByXPath('/html/body/div/div[1]/div/div[3]/div[2]/div[2]/div/div/div[1]/table[2]/tbody/tr[3]/td[3]');
  Memo1.Append('=== Hasil Perhitungan ===');
  Memo1.Append('Anies-Muhaimain : '+anies.Text);
  Memo1.Append('Prabowo-Gibran : '+prabowo.Text);
  Memo1.Append('Ganjar-Mahfud : '+ganjar.Text);
end;

Kedelapan, mendownload Form C1 Hasil alias Plano. Proses download ini dilakukan dengan dua tahap. Pertama melakukan click pada button Lihat Form Pindai C Hasil menggunakan script di bawah ini, letakan di dalam tombol Buka C1 Hasil/Plano

  Robot.ExecuteScript('var xpath = "/html/body/div/div[1]/div/div[3]/div[2]/div[2]/div/div/button";'+
                        'function getElementByXpath(path) {'+
                        'return document.evaluate('+
                        '  path,'+
                        '  document,'+
                        '  null,'+
                        '  XPathResult.FIRST_ORDERED_NODE_TYPE,'+
                        '  null'+
                        ').singleNodeValue;'+
                        '}'+
                        'var element = getElementByXpath(xpath);'+
                        'if (!element) {'+
                        'throw new Error("Error: cannot find an element with XPath(" + xpath + ")");'+
                        '}'+
                        'element.click();');   

Kedua, buat folder di dalam folder projek dengan nama Download_C1 untuk menampung hasil download. Adapun proses dowload menggunakan library tambahan yaitu synapse. Silahkan download kemudian tambahkan ke dalam projek (package - open package file (.lpk) - use - add to project). Selanjutnya, karena dalam proses ini kita akan mendownload file dari situs https, jadi kita memerlukan library openssl untuk windows silahkan download di sini. Ekstrak kemudian masukan semua filenya ke dalam folder projek. Lalu tambahkan unit httpsend dan ssl_openssl di dalam uses projek. Terakhir, untuk proses download saya menggunakan script di bawah ini, letakan di dalam tombol Download C1. Source code lengkap ada di github

var
  c1_hasil : TWebElements;
  httpClient: THTTPSend;
begin
  c1_hasil := Robot.FindElementsByXPath('/html/body/div/div[1]/div/div[3]/div[2]/div[2]/div/div/div[4]/div[2]/div/div/a');
  Memo1.Append('=== Download C1 Hasil ===');
  for i := 0 to c1_hasil.Count - 1 do
  begin
       httpClient:= THTTPSend.Create;
       if httpClient.HTTPMethod('GET', c1_hasil.Items[i].AttributeValue('href')) then
            begin
            httpClient.Document.SaveToFile('Download_C1/c1_'+IntToStr(i)+'_xx.jpg');
            Memo1.Append('C1 Hasil Berhasil didownload...');
            end;
       httpClient.Free;
  end;
end;  

oke, that's it.. semoga bermanfaat