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 bottimeout=10— batas waktu 10 detik agar program tidak hang selamanyaresponse.status_code—200berarti sukses,404berarti 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
| Metode | Kegunaan |
|---|---|
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:
- Setup — instalasi
requests,BeautifulSoup, danlxmlvia virtual environment - Fetch — mengambil HTML dengan
requests.get()beserta header dan timeout - Parse — memparsing HTML dengan
BeautifulSoupmenggunakanfind(),find_all(), dan selector CSS - Extract — mengekstrak data spesifik dari elemen HTML
- 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
Apakah web scraping legal?
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.