Scrapping data pemilu 2024 membuat custom Web Apps dan deploy ke vercel

Category: Tutorial | 174 views

February 15, 2024


Scrapping data pemilu 2024 membuat custom Web Apps dan deploy ke vercel

Halo! Pada kesempatan kali ini, saya akan membagikan tutorial mengenai cara melakukan scraping data dari website KPU untuk mengambil data quick count dan menampilkan data tersebut kembali menggunakan Requests dan Flask . Sebelum masuk ke dalam pembahasan, mari kita simak terlebih dahulu apa itu Python3.

Apa itu Python3 ?

Python3 adalah bahasa pemrograman tingkat tinggi yang bersifat interpretatif, dinamis, dan memiliki banyak kegunaan. Bahasa ini populer karena mudah dipelajari, digunakan, dan memiliki banyak pustaka (library) yang mendukung berbagai macam tugas pemrograman. Python3 banyak digunakan untuk berbagai macam keperluan, seperti:

  • Analisis data
  • Pemrograman web
  • Pemrograman ilmiah
  • Pembelajaran mesin
  • Otomasi
  • Dan banyak lagi

Apa itu Scraping Data?

Scraping data adalah proses pengambilan data dari website secara otomatis. Data yang diambil dapat berupa teks, gambar, video, atau format lainnya. Scraping data dapat dilakukan dengan berbagai cara, salah satunya menggunakan bahasa pemrograman Python3.

Selanjutnya apa saja library yang perlu disiapkan?

Sebelum menentukan library biasanya saya melakukan survey dulu terhadap web yang akan di scrapping datanya dengan cara membuka halaman web tersebut, berikut adalah hasil analisa saya mengenai web KPU

Web aplikasi diatas tidak langsung menampilkan data data di HTML nya ( akan melakukan request ulang dengan menggunakan metode AJAX atau Fetch atau curl pada api lainya )
maka dari itu kita tidak bisa langsung menggunakan Library beautifulsoup karena webnya bersifat dynamic menggunakan Javascript untuk memanggil kontenya
nah benar setelah web berhasil diload akan otomatis melakukan request pada API tertentu yang sudah di point sebelumnya. berarti library yang cocok untuk project ini adalah Requests
kita dapat langsung melakukan pemanggilan API seperti yang dilakukan web KPU diatas menggunakan library Requests
 
library yang digunakan untuk scrapping data :  Requests. karena saya akan menampilkan kembali data data yang telah discrapping maka butuh library web backend disini saya menggunakan : Flask & Flask Humanize
baik saatnya membuat project baru di pycharm / kode editor anda
 
install dulu library yang dibutuhkan tadi di terminal pycharm dengan menjalankan command berikut ini

Install library Requests 

pip install requests

Install library Flask

pip install Flask

okayy setelah semua library yang dibutuhkan berhasil diinstall waktunya membuat Helper atau fungsi bantuan yang nanti akan dipanggil di main program, disini saya membuatnya di dalam folder lib dengan nama requestHelper.py

import requests


class requestHelper:
    BASE_URL = "https://sirekap-obj-data.kpu.go.id/"

    def __init__(self):
        self.request = requests.Session()
        self.request.headers.update({
            "Accept": "application/json",
            "Content-Type": "application/json"
        })
        self.response = None

Penjelasan kode diatas adalah :

  • Melakukan import library requests
  • Menginisialisasi BASE URL API yang akan digunakan untuk requests 
  • Membuat init constructor yang berisi request session 
nah untuk selanjutnya bagaimana ? mari kita simak dari foto diatas telah saya beri garis kotak merah terdapat 3 json Request yang dilakukan berarti disini kita juga membuat 3 method untuk mengambil data tersebut dan
data yang akan diambil adalah :
 
Data nama Paslon

Data Daerah

Data Tabel

 
dari ketiga endpoint diatas kita dapat membuat method di dalam class requestHelper sebagai berikut ini
    def get_wilayah(self):
        self.response = self.request.get(self.BASE_URL + "wilayah/pemilu/ppwp/0.json")
        return self.response.json()

    def get_paslon(self):
        self.response = self.request.get(self.BASE_URL + "pemilu/ppwp.json")
        return self.response.json()

    def get_table(self):
        self.response = self.request.get(self.BASE_URL + "pemilu/hhcw/ppwp.json")
        return self.response.json()

    def get_count(self):
        serialized_data_wilayah = []
        serialized_data_paslon = []
        final_data = []

        data_paslon = self.get_paslon()
        for paslon in data_paslon:
            serialized_data_paslon.append({
                "id_paslon": paslon,
                "nama": data_paslon[paslon]["nama"],
                "nomor_urut": data_paslon[paslon]["nomor_urut"],
            })

        data_wilayah = self.get_wilayah()
        for wilayah in data_wilayah:
            serialized_data_wilayah.append({
                "id": wilayah["id"],
                "nama": wilayah["nama"],
                "kode": wilayah["kode"],
            })

        data_table = self.get_table()
        for wilayah in range(len(serialized_data_wilayah)):
            wilayah_data = data_table.get("table")[serialized_data_wilayah[wilayah].get("kode")]
            modified_data = {}
            for key, value in wilayah_data.items():
                if key in [str(paslon['id_paslon']) for paslon in serialized_data_paslon]:
                    nomor_urut = next(paslon['nomor_urut'] for paslon in serialized_data_paslon if paslon['id_paslon'] == key)
                    modified_data[nomor_urut] = value
                else:
                    modified_data[key] = value

            final_data.append({
                "data_wilayah": serialized_data_wilayah[wilayah],
                "data_paslon": modified_data
            })


        return {
            'data': final_data,
            'data_paslon': serialized_data_paslon,
            'chart': data_table.get('chart'),
            'last_updated': data_table.get('ts'),
            'progres': data_table.get('progres'),
        }

Penjelasan kode diatas adalah :

  • Membuat 3 method untuk mengambil data Dearah, Paslon & Table
  • Method GetCount digunakan untuk menampung semua data final yang akan ditampilkan ke halaman web

nah untuk versi lengkapnya dapat dilihat di github link berikut ini : requestHelper.py

saatnya melakukan test pada method yang telah dibuat sebelumnya. membuat file main.py

from lib.requestHelper import requestHelper
import json

request = requestHelper()
data = request.get_count()
print(
    json.dumps(data, indent=4)
)

Penjelasan kode diatas adalah :

  • Melakukan import Class requestHelper
  • Menginstansiasi Class requestHelper
  • Memanggil dan menampilkan method get_count dari class requestHelper

Hasilnya jika berhasil akan tampil seperti berikut ini :

 

okayy kita telah berhasil melakukan scrapping data dari web KPU menggunakan library requests, lalu bagaimana cara menampilkan data itu kembali ke web custom buatan kita ?
baik kita lakukan pembuatan file lagi dengan nama app.py di dalam app.py ini akan menampung library flask yang digunakan untuk Backend Webnya 
from flask import Flask, request, jsonify, render_template
from flask_humanize import Humanize

from lib.requestHelper import requestHelper

app = Flask(__name__, template_folder="templates")
humanize = Humanize(app)


@humanize.localeselector
def get_locale():
    return 'id_ID'


@app.route("/")
def index():
    request_helper = requestHelper()
    data = request_helper.get_count()
    return render_template(
        "index.html",
        data_paslon=data["data_paslon"],
        data_chart=data["chart"],
        data_table=data["data"],
        data_last_updated=data["last_updated"],
        data_progres=data["progres"],

    )

Penjelasan kode diatas adalah :

  • Melakukan import Class requestHelper dari modul requestHelper yang berada dalam direktori lib. Kemudian, sebuah aplikasi Flask dibuat dengan nama app, dengan menentukan folder template-nya sebagai "templates". Dilanjutkan dengan penggunaan ekstensi Flask-Humanize untuk membantu dalam pemformatan data.
  • Fungsi get_locale() digunakan sebagai penentu lokal yang akan digunakan, dalam kasus ini, lokal yang diatur adalah id_ID untuk Bahasa Indonesia.
  • Rute utama / diatur untuk menangani permintaan ke root URL. Saat rute ini diakses, objek requestHelper dibuat untuk membantu dalam memproses permintaan. Data yang diperoleh kemudian diteruskan ke template index.html menggunakan fungsi render_template. Data tersebut meliputi informasi tentang jumlah paslon, data grafik, data tabel, waktu terakhir diperbarui, dan kemajuan data.

nah setelah membuat app.py jangan lupa untuk membuat folder templates dan berisi file index.html berikut ini adalah contoh dari file html nya 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta content="width=device-width, initial-scale=1.0" name="viewport">
    <title>Hasil Hitung Suara Pemilu Presiden & Wakil Presiden RI 2024</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
    <style>
        #hasil-perolehan-suara {
            font-size: 20px;
            font-weight: bold;
            text-align: center;
            margin-top: 20px;
        }
        .card-style {
            font-size: 20px;
            font-weight: bold;
        }

    </style>

</head>
<body>

<div class="container" style="margin-top: 120px; margin-bottom: 120px;">
    <div class="row justify-content-center">
        <div class="col-md-10">
            <h1 class="text-center">HASIL HITUNG SUARA PEMILU PRESIDEN & WAKIL PRESIDEN RI 2024</h1>
            <p class="text-center">Updated at : {{ data_last_updated }}</p>
            <p class="text-center"><span class="badge bg-info">Progress : {{ data_progres.total }} dari {{ data_progres.progres }} TPS</span></p>
        </div>
        <div id="chart-container" style="width: 120%; height: 600px;"></div>
        {% for paslon in data_paslon %}
        <div class="col-md-4">
            <div class="card mb-3">
                <div class="card-header text-center card-style">
                    {{ paslon.nama.split('-')[0] }}<br>
                    {{ paslon.nama.split('-')[1] }}.
                </div>
                <div class="card-body">
                    {% for key, value in data_chart.items() %}
                    {% if key == paslon.id_paslon: %}
                    <div class="row">
                        <div class="col-md-12" id="hasil-perolehan-suara">
                            {{ value|humanize('intcomma') }} Suara
                        </div>
                    </div>
                    {% endif %}
                    {% endfor %}


                </div>
            </div>
        </div>
        {% endfor %}

    </div>
    <div class="container" style="margin-top: 10px; margin-bottom: 120px;">
        <div class="row justify-content-center">
            <!-- Your other content here -->
            <div class="col-md-13">
                <!-- DataTables container -->
                <div class="table-responsive">
                    <table class="table table-bordered table-hover" id="table-data">
                        <thead>
                        <tr class="table-primary text-center">
                            <th>#</th>
                            <th>Wilayah</th>
                            <th>Progress</th>
                            {% for paslon in data_paslon %}
                            <th>{{ paslon.nama.split('-')[0] }}<br>{{ paslon.nama.split('-')[1] }}</th>
                            {% endfor %}
                        </tr>
                        </thead>
                        <tbody class="text-center" style="font-size: 20px;">
                        {% for data in data_table %}
                        <tr>
                            <td>{{ loop.index }}</td>
                            <td>{{ data.data_wilayah.nama }}</td>
                            <td>{{ data.data_paslon.persen|humanize('intcomma') }}%</td>
                            <td>{{ data.data_paslon.1|safe|humanize('intcomma') }}</td>
                            <td>{{ data.data_paslon.2|safe|humanize('intcomma') }}</td>
                            <td>{{ data.data_paslon.3|safe|humanize('intcomma') }}</td>
                        </tr>
                        {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

<div class="container text-center" style="font-size: 20px; font-weight: bold; background-color: #f8d7da; padding: 20px; width: 100%;">
    <div class="row justify-content-center">
        <div class="col-md-10">
            <p class="text-center">Data diambil dari API KPU : https://pemilu2024.kpu.go.id/ </p>
            <p class="text-center">Tampilan web ini dibuat oleh : <a href="https://sandroputra.com" target="_blank">Sandro Putra</a></p>
        </div>
    </div>
</div>


<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>


<script>
    // Initialize DataTables
    $(document).ready(function() {
        // Extracting data from HTML
        var paslon1Data = [];
        var paslon2Data = [];
        var paslon3Data = [];
        var wilayah = [];

        {% for data in data_table %}
        paslon1Data.push({{ data.data_paslon.1 }});
        paslon2Data.push({{ data.data_paslon.2 }});
        paslon3Data.push({{ data.data_paslon.3 }});
        wilayah.push("{{ data.data_wilayah.nama }}");
        {% endfor %}

        // Create chart
        var options = {
            chart: {
                type: 'line',
                height: 600,
                width: '100%',
                toolbar: {
                    show: true,
                },
                zoom: {
                    enabled: true
                },
            },
            colors: ['#388E3C', '#0288D1', '#D32F2F'], // Change colors here
            series: [{
                name: 'Paslon 1',
                data: paslon1Data
            }, {
                name: 'Paslon 2',
                data: paslon2Data
            }, {
                name: 'Paslon 3',
                data: paslon3Data
            }],
            xaxis: {
                categories: wilayah
            },
            yaxis: {
                title: {
                    text: 'Suara'
                }
            },
            tooltip: {
                y: {
                    formatter: function (val) {
                        return val.toLocaleString() + " Suara"
                    }
                }
            }
        };

        var chart = new ApexCharts(document.querySelector("#chart-container"), options);
        chart.render();

    });
</script>
</body>
</html>

dari html diatas kita melakukan parsing data dari backend ke html dengan cara 

<p class="text-center">Updated at : {{ data_last_updated }}</p>

kemudian membuat chart untuk menampilkan presentase dengan apexchart.

nah ketika html dan backend py telah berhasil dibuat saatnya melakukan test dengan membuat file server.py. dimana server.py ini akan bekerja seperti webserver untuk menjalankan kode yang telah dibuat sebelumnya berikut ini adalah kodenya

from app import app

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5020, debug=True)

nah ketika dijalankan server.py di terminal memiliki tampilan seperti berikut ini maka program telah berhasil dibuat

Selanjutnya adalah membuat konfigurasi vercel.json yang digunakan untuk publish ke web vercel dengan bantuan github, berikut ini adalah konfigurasinya :

{
    "version": 2,
    "builds": [
        {
            "src": "./server.py",
            "use": "@vercel/python"
        }
    ],
    "routes": [
        {
            "src": "/(.*)",
            "dest": "server.py"
        }
    ]
}

setelah semuanya berhasil dibuat langkah terakhir sebelum push repository adalah melaukan freeze requirements yang dibutuhkan dengan command berikut ini

pip freeze > requirements.txt

command diatas akan melakukan extract semua library yang dibutuhkan kedalam file requirements.txt, baik selanjutnya adalah tinggal melakukan push ke github anda masing masing dan buka vercel untuk melakukan deploy di vercel. berikut ini adalah tampilan ketika web sudah di vercel 

okayy sekian tutorial Scrapping data pemilu 2024 dan membuat custom Web Apps deploy vercel semoga bermanfaat ✨?

Link Repository : Github api-real-count-2024
 

Comments (2)

avatar

An
Gacor abangkuuhh?

February 15, 2024
avatar

Anonymous
Nice Tutorial ?

February 15, 2024

Leave a comment