Langsung ke konten
KamusNgoding
Terapan Python 4 menit baca

Membangun Web Scraper dengan Python: Tutorial Step-by-Step

#python #web scraping #beautifulsoup #requests #proyek

Membangun Web Scraper dengan Python: Tutorial Langkah demi Langkah

Pendahuluan

Web scraping adalah teknik mengambil data dari halaman web secara otomatis. Bayangkan Anda ingin membangun aplikasi agregator harga — Anda perlu mengambil ribuan data harga dari berbagai sumber sekaligus. Di sinilah web scraper berperan.

Python adalah pilihan utama untuk web scraping karena ekosistem library-nya yang lengkap dan sintaksnya yang ekspresif. Dalam tutorial ini, kita akan membangun web scraper dari nol menggunakan dua library utama: requests untuk mengambil HTML dan BeautifulSoup untuk memparsing datanya.


Persiapan Lingkungan: Instalasi Python dan Library

Sebelum mulai, pastikan Python 3.8+ sudah terinstal. Kemudian ikuti langkah-langkah berikut.

Langkah 1: Buat Virtual Environment

Virtual environment memastikan dependensi proyek ini tidak bertabrakan dengan proyek lain.

# Buat virtual environment baru bernama .venv
python -m venv .venv

Langkah 2: Aktifkan Virtual Environment

Perintah aktivasi berbeda tergantung sistem operasi:

# Linux / macOS
source .venv/bin/activate

# Windows (Command Prompt)
.venv\Scripts\activate.bat

# Windows (PowerShell)
.venv\Scripts\Activate.ps1

Setelah aktif, prompt terminal akan menampilkan nama environment, misalnya (.venv).

Langkah 3: Buat File requirements.txt

Buat file requirements.txt di folder proyek untuk mendokumentasikan dependensi. Isi file ini adalah daftar nama library, satu per baris:

requests
beautifulsoup4
lxml

Langkah 4: Instal Dependensi

# Instal semua library yang tercantum di requirements.txt
pip install -r requirements.txt

Langkah 5: Verifikasi Instalasi

# Verifikasi ketiga library berhasil diinstal
python -c "import requests; from bs4 import BeautifulSoup; import lxml; print('Semua package berhasil diinstal')"

# Output yang diharapkan:
# > Semua package berhasil diinstal

Keterangan library yang diinstal:

  • requests — mengirim HTTP request dan mengambil respons HTML
  • beautifulsoup4 — memparsing dan menavigasi struktur HTML
  • lxml — parser HTML yang cepat, digunakan oleh BeautifulSoup

Mengambil Data HTML dengan requests

Library requests memungkinkan kita mengirim HTTP GET request ke URL tertentu dan mendapatkan respons berupa HTML mentah.

import requests

# URL halaman yang akan diambil
url = "https://books.toscrape.com/"

# Header sederhana agar request terlihat seperti dari browser biasa
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}

# Kirim request GET ke website dengan batas waktu 10 detik
response = requests.get(url, headers=headers, timeout=10)

# Hentikan program jika respons gagal (misalnya 404 atau 500)
response.raise_for_status()

# Tampilkan status HTTP dan panjang isi HTML
print(f"Status code: {response.status_code}")
print(f"Panjang HTML: {len(response.text)} karakter")

# Output yang diharapkan:
# > Status code: 200
# > Panjang HTML: [jumlah karakter HTML]

Beberapa hal penting di sini:

  • headers — menyertakan User-Agent agar server tidak memblokir request yang terlihat seperti bot
  • timeout=10 — batas waktu 10 detik agar program tidak hang selamanya
  • response.status_code200 berarti sukses, 404 berarti halaman tidak ditemukan

Selalu periksa status code sebelum memproses respons:

import requests

# URL contoh yang akan diambil isinya
url = "https://example.com"

# Kirim request GET ke halaman web
response = requests.get(url, timeout=10)

# Cek apakah request berhasil
if response.status_code == 200:
    html_content = response.text
    print("Halaman berhasil diambil.")
    print(html_content[:100])  # Tampilkan 100 karakter pertama
else:
    print(f"Gagal mengambil halaman: {response.status_code}")
    html_content = None

# Output yang diharapkan:
# > Halaman berhasil diambil.
# > <!doctype html><html><head><title>Example Domain</title>...

Untuk mengambil data dalam jumlah besar, tambahkan jeda antar request agar tidak membebani server target:

import time
import requests

# Daftar URL yang akan diambil satu per satu
urls = [
    "https://books.toscrape.com/catalogue/page-1.html",
    "https://books.toscrape.com/catalogue/page-2.html",
    "https://books.toscrape.com/catalogue/page-3.html",
]

for url in urls:
    try:
        response = requests.get(url, timeout=10)
        print(f"Mengambil: {url} - {response.status_code}")
    except requests.RequestException as e:
        print(f"Gagal mengambil: {url} - {e}")

    # Beri jeda 1 detik agar request tidak terlalu cepat
    time.sleep(1)

# Output yang diharapkan:
# > Mengambil: https://books.toscrape.com/catalogue/page-1.html - 200
# > Mengambil: https://books.toscrape.com/catalogue/page-2.html - 200
# > Mengambil: https://books.toscrape.com/catalogue/page-3.html - 200

Parsing HTML dan Mengekstrak Informasi dengan BeautifulSoup

Setelah mendapatkan HTML mentah, kita gunakan BeautifulSoup untuk memparsing dan menavigasi strukturnya seperti sebuah pohon elemen.

import requests
from bs4 import BeautifulSoup

# URL halaman utama katalog buku
url = "https://books.toscrape.com/"

# Kirim permintaan ke website
response = requests.get(url, timeout=10)
response.raise_for_status()

# Parse HTML dengan parser bawaan Python
soup = BeautifulSoup(response.text, "html.parser")

# Ambil semua elemen artikel yang mewakili satu buku
buku_list = soup.find_all("article", class_="product_pod")

print(f"Jumlah buku ditemukan: {len(buku_list)}")

if buku_list:
    judul_pertama = buku_list[0].h3.a["title"]
    print(f"Judul buku pertama: {judul_pertama}")

# Output yang diharapkan:
# > Jumlah buku ditemukan: 20
# > Judul buku pertama: A Light in the Attic

Metode Utama BeautifulSoup

MetodeKegunaan
find(tag, attrs)Temukan elemen pertama yang cocok
find_all(tag, attrs)Temukan semua elemen yang cocok
select(css_selector)Gunakan CSS selector
.text / .get_text()Ambil teks dalam elemen
.get("attr")Ambil nilai atribut

Contoh mengekstrak judul, harga, dan rating dari beberapa buku:

from bs4 import BeautifulSoup

# Contoh HTML sederhana agar kode bisa langsung dijalankan tanpa koneksi internet
html = """
<div class="book">
    <h3><a title="Belajar Python Dasar">Belajar Python Dasar</a></h3>
    <p class="price_color">£23.88</p>
    <p class="star-rating Three"></p>
</div>
<div class="book">
    <h3><a title="Python untuk Data Analysis">Python untuk Data Analysis</a></h3>
    <p class="price_color">£35.02</p>
    <p class="star-rating Five"></p>
</div>
"""

soup = BeautifulSoup(html, "html.parser")
buku_list = soup.find_all("div", class_="book")

for buku in buku_list:
    judul = buku.find("h3").find("a").get("title")
    harga = buku.find("p", class_="price_color").text.strip()
    rating_tag = buku.find("p", class_="star-rating")
    rating = rating_tag.get("class")[1] if rating_tag else "Tidak diketahui"

    print(f"Judul: {judul}")
    print(f"Harga: {harga}")
    print(f"Rating: {rating}")
    print("---")

# Output yang diharapkan:
# > Judul: Belajar Python Dasar
# > Harga: £23.88
# > Rating: Three
# > ---
# > Judul: Python untuk Data Analysis
# > Harga: £35.02
# > Rating: Five
# > ---

Contoh Kasus Nyata: Scraper Multi-Halaman ke CSV

Mari kita bangun scraper lengkap yang mengambil semua buku dari beberapa halaman dan menyimpannya ke file CSV.

import csv
import time

import requests
from bs4 import BeautifulSoup

BASE_URL = "https://books.toscrape.com/catalogue/page-{}.html"
OUTPUT_FILE = "buku.csv"


def ambil_halaman(url):
    """Mengambil HTML dari URL lalu mengubahnya menjadi BeautifulSoup."""
    headers = {"User-Agent": "Mozilla/5.0"}
    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        return BeautifulSoup(response.text, "html.parser")
    except requests.RequestException as error:
        print(f"Gagal mengambil {url}: {error}")
        return None


def ekstrak_buku(soup):
    """Mengekstrak data buku dari satu halaman katalog."""
    hasil = []
    daftar_buku = soup.find_all("article", class_="product_pod")

    for buku in daftar_buku:
        link = buku.find("h3").find("a")
        harga_tag = buku.find("p", class_="price_color")
        rating_tag = buku.find("p", class_="star-rating")
        stok_tag = buku.find("p", class_="instock availability")

        judul = link.get("title", "Tidak ada judul")
        harga = harga_tag.get_text(strip=True) if harga_tag else "Tidak ada harga"

        rating = "Tidak diketahui"
        if rating_tag:
            kelas_rating = rating_tag.get("class", [])
            if len(kelas_rating) > 1:
                rating = kelas_rating[1]

        stok = "Tersedia" if stok_tag and "In stock" in stok_tag.get_text() else "Habis"

        hasil.append({
            "judul": judul,
            "harga": harga,
            "rating": rating,
            "stok": stok,
        })

    return hasil


def simpan_ke_csv(data, filename):
    """Menyimpan data buku ke file CSV."""
    if not data:
        print("Tidak ada data untuk disimpan.")
        return

    with open(filename, "w", newline="", encoding="utf-8") as file_csv:
        writer = csv.DictWriter(file_csv, fieldnames=["judul", "harga", "rating", "stok"])
        writer.writeheader()
        writer.writerows(data)

    print(f"Data berhasil disimpan ke {filename}")


def main():
    semua_buku = []
    total_halaman = 5  # Ambil 5 halaman pertama

    for halaman in range(1, total_halaman + 1):
        url = BASE_URL.format(halaman)
        print(f"Memproses halaman {halaman}...")

        soup = ambil_halaman(url)
        if soup is None:
            continue

        buku_halaman = ekstrak_buku(soup)
        semua_buku.extend(buku_halaman)

        print(f"> {len(buku_halaman)} buku ditemukan")
        time.sleep(1)

    print(f"Total buku terkumpul: {len(semua_buku)}")
    simpan_ke_csv(semua_buku, OUTPUT_FILE)


if __name__ == "__main__":
    main()

# Output yang diharapkan:
# > Memproses halaman 1...
# > 20 buku ditemukan
# > Memproses halaman 2...
# > 20 buku ditemukan
# > ...
# > Total buku terkumpul: 100
# > Data berhasil disimpan ke buku.csv

Output CSV yang dihasilkan akan terlihat seperti ini:

judul,harga,rating,stok
A Light in the Attic,£51.77,Three,Tersedia
Tipping the Velvet,£53.74,One,Tersedia
Soumission,£50.10,One,Tersedia

Kesimpulan

Dalam tutorial ini kita telah membangun web scraper fungsional dari nol:

  1. Setup — instalasi requests, BeautifulSoup, dan lxml via virtual environment
  2. Fetch — mengambil HTML dengan requests.get() beserta header dan timeout
  3. Parse — memparsing HTML dengan BeautifulSoup menggunakan find(), find_all(), dan selector CSS
  4. Extract — mengekstrak data spesifik dari elemen HTML
  5. Save — menyimpan hasil ke CSV dengan modul csv

Kunci scraping yang baik bukan hanya soal teknik, tapi juga etika: hormati robots.txt, sisipkan jeda antar request, dan jangan membebani server target.


Pertanyaan yang Sering Diajukan

Web scraping berada di zona abu-abu hukum dan bergantung pada kebijakan masing-masing situs. Selalu periksa file robots.txt di domain target (misalnya https://example.com/robots.txt) dan baca syarat layanan (Terms of Service) situs tersebut. Scraping untuk keperluan riset pribadi umumnya diizinkan, tetapi menggunakan data secara komersial atau membebani server bisa melanggar ketentuan.

Kenapa request saya diblokir oleh website?

Banyak situs mendeteksi bot berdasarkan pola request yang terlalu cepat atau header yang tidak wajar. Solusinya: tambahkan header User-Agent yang menyerupai browser sungguhan, sisipkan jeda time.sleep() antar request, dan hindari mengirim ribuan request dalam waktu singkat. Jika situs menggunakan JavaScript untuk merender konten, requests tidak akan cukup — Anda perlu library seperti selenium atau playwright.

Apa perbedaan find() dan find_all() di BeautifulSoup?

find() mengembalikan satu elemen pertama yang cocok dengan kriteria pencarian, atau None jika tidak ditemukan. find_all() mengembalikan list semua elemen yang cocok — jika tidak ada yang cocok, hasilnya adalah list kosong []. Gunakan find() saat Anda hanya butuh satu elemen (misalnya judul halaman), dan find_all() saat Anda ingin mengiterasi banyak elemen sekaligus (misalnya semua kartu produk).

Bagaimana cara menyimpan data ke format selain CSV?

Selain CSV, data hasil scraping bisa disimpan ke JSON menggunakan modul json bawaan Python (json.dump()), ke database SQLite dengan modul sqlite3, atau ke file Excel menggunakan library openpyxl. Untuk proyek kecil, CSV dan JSON sudah lebih dari cukup. Pilih format sesuai kebutuhan: JSON cocok untuk data bersarang (nested), CSV cocok untuk data tabular yang akan dibuka di spreadsheet.

Artikel Terkait