Ketika kamu sudah nyaman melakukan web scraping dengan BeautifulSoup, kamu mungkin mulai menyadari batasannya: setiap kali struktur halaman berubah kamu harus menulis ulang banyak kode, dan scraping ratusan halaman terasa lambat serta sulit dirawat. Di sinilah Scrapy hadir. Scrapy adalah framework web crawling paling populer di Python yang dirancang khusus untuk scraping berskala besar — lengkap dengan sistem spider, selector bawaan, pipeline pemrosesan data, hingga penanganan permintaan asinkron. Dalam tutorial ini kamu akan membangun spider Scrapy pertamamu dari nol dan memahami cara kerjanya secara menyeluruh.
Apa Itu Scrapy dan Kapan Memakainya?
Scrapy bukan sekadar library — ia adalah framework lengkap dengan struktur proyek, mesin crawling asinkron berbasis Twisted, dan ekosistem ekstensi. Berbeda dengan pendekatan manual, Scrapy memisahkan tanggung jawab ke dalam beberapa komponen:
- Spider: kelas yang menentukan halaman mana yang diambil dan data apa yang diekstrak.
- Item: struktur data yang mendefinisikan hasil scraping.
- Item Pipeline: tahapan untuk membersihkan, memvalidasi, dan menyimpan data.
- Middleware & Settings: tempat mengatur user-agent, jeda antar permintaan, dan proxy.
Kamu sebaiknya memilih Scrapy ketika target scraping mencapai puluhan hingga jutaan halaman, atau ketika kamu butuh alur crawling yang terstruktur dan mudah diuji. Untuk kasus satu halaman sederhana, BeautifulSoup sudah cukup; untuk halaman yang merender konten lewat JavaScript, gunakan Playwright. Scrapy duduk di antara keduanya: cepat, asinkron, dan kuat untuk crawling situs statis dalam skala besar.
Persiapan: Install Scrapy
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install scrapy
# Cek versi
scrapy version
Membuat Proyek Scrapy Pertama
Semua proyek Scrapy diawali dengan satu perintah. Jalankan perintah berikut di direktori kerja kamu:
scrapy startproject tokoscraper
cd tokoscraper
# Struktur yang dihasilkan:
# tokoscraper/
# ├── scrapy.cfg
# └── tokoscraper/
# ├── items.py
# ├── middlewares.py
# ├── pipelines.py
# ├── settings.py
# └── spiders/
Perintah ini membuat kerangka proyek lengkap. File items.py untuk mendefinisikan struktur data, pipelines.py untuk memproses hasil, settings.py untuk konfigurasi global, dan folder spiders/ untuk menaruh spider kamu.
Menulis Spider Pertamamu
Mari kita buat spider untuk mengambil judul, harga, dan rating buku dari situs latihan books.toscrape.com (situs demo yang memang disediakan untuk belajar scraping). Buat file baru tokoscraper/spiders/books.py:
import scrapy
class BooksSpider(scrapy.Spider):
name = "books"
start_urls = ["https://books.toscrape.com/"]
def parse(self, response):
for book in response.css("article.product_pod"):
yield {
"title": book.css("h3 a::attr(title)").get(),
"price": book.css("p.price_color::text").get(),
"rating": book.css("p.star-rating::attr(class)").get(),
}
Penjelasan singkat:
nameadalah identitas spider saat dijalankan via CLI.start_urlsadalah daftar URL awal yang akan di-request.- Metode
parse()menerima objekresponsedan harus meng-yielddictionary item atau request lanjutan. - Selektor
response.css()memakai sintaks CSS;::textmengambil teks, sedangkan::attr(title)mengambil nilai atribut HTML.
Menjalankan Spider dan Menyimpan Hasil
Jalankan spider dengan perintah crawl dan simpan hasilnya ke JSON:
scrapy crawl books -o books.json
# Atau lihat langsung di terminal
scrapy crawl books
Flag -o books.json akan menulis seluruh hasil ke file JSON secara otomatis — tanpa perlu menulis kode tambahan. Scrapy juga mendukung format csv dan jsonl dengan cara yang sama.
Memahami Selector CSS dan XPath
Scrapy punya dua cara menyeleksi elemen: CSS (lebih ringkas) dan XPath (lebih fleksibel). Keduanya bisa dipakai bersamaan. Cobalah bereksperimen lewat Scrapy Shell yang interaktif:
scrapy shell "https://books.toscrape.com/"
# Di dalam shell:
>>> response.css("title::text").get()
# 'All products | Books to Scrape - Sandbox'
>>> response.css("article.product_pod").xpath(".//h3/a/@title").get()
# 'A Light in the Attic'
>>> response.xpath("//a[contains(@title, 'Light')]/@href").get()
# 'a-light-in-the-attic_1000/index.html'
Tips: gunakan CSS untuk mayoritas kasus karena lebih mudah dibaca, lalu beralih ke XPath saat kamu butuh mencocokkan berdasarkan teks atau navigasi antar-elemen yang lebih rumit.
Mengikuti Link dan Pagination
Untuk mengambil seluruh 1000 buku, spider harus mengikuti link halaman berikutnya. Kita modifikasi parse():
import scrapy
class BooksSpider(scrapy.Spider):
name = "books"
start_urls = ["https://books.toscrape.com/"]
def parse(self, response):
for book in response.css("article.product_pod"):
yield {
"title": book.css("h3 a::attr(title)").get(),
"price": book.css("p.price_color::text").get(),
"rating": book.css("p.star-rating::attr(class)").get(),
}
next_page = response.css("li.next a::attr(href)").get()
if next_page is not None:
yield response.follow(next_page, callback=self.parse)
response.follow() membangun request baru secara otomatis (termasuk menangani URL relatif) dan memanggil parse() lagi untuk halaman berikutnya. Inilah kekuatan utama Scrapy: mengikuti ribuan link hanya dengan beberapa baris kode, semuanya berjalan secara asinkron.
Membersihkan Data dengan Item Pipeline
Data mentah sering kali kotor. Rating dari p.star-rating misalnya bernilai star-rating Three, dan harga masih berupa string £51.77. Kita definisikan Item lalu bersihkan lewat pipeline. Pertama, definisikan item di items.py:
import scrapy
class BookItem(scrapy.Item):
title = scrapy.Field()
price = scrapy.Field()
rating = scrapy.Field()
Lalu daftarkan pipeline di settings.py dan tulis logika pembersihannya di pipelines.py:
# settings.py
ITEM_PIPELINES = {
"tokoscraper.pipelines.PricePipeline": 300,
}
# pipelines.py
class PricePipeline:
def process_item(self, item, spider):
# Bersihkan harga: "£51.77" -> 51.77
raw = (item.get("price") or "").replace("£", "").strip()
item["price"] = float(raw)
# Rating: "star-rating Three" -> "Three"
item["rating"] = (item.get("rating") or "").replace("star-rating ", "")
return item
Setiap item yang di-yield oleh spider akan melewati pipeline secara berurutan. Di sinilah kamu bisa membersihkan data, membuang item duplikat, atau menyimpannya ke database.
Penting — Etika Scraping: Selalu hormati robots.txt dan aturan situs target. Jangan membanjiri server dengan permintaan, dan pastikan aktivitas scraping kamu sesuai hukum serta Terms of Service situs tersebut. Scrapy menyediakan ROBOTSTXT_OBEY = True untuk otomatis mematuhi robots.txt.
Menghindari Block: User-Agent dan Download Delay
Banyak situs memblokir bot berdasarkan user-agent bawaan Scrapy. Atur konfigurasi di settings.py agar spider kamu lebih sopan dan sulit dikenali sebagai bot:
# settings.py
ROBOTSTXT_OBEY = True
DOWNLOAD_DELAY = 1 # jeda 1 detik antar permintaan
USER_AGENT = "Mozilla/5.0 (compatible; TokoScraperBot/1.0; +https://example.com/bot)"
CONCURRENT_REQUESTS = 8 # batasi jumlah permintaan paralel
DOWNLOAD_DELAY dan CONCURRENT_REQUESTS adalah dua kunci agar kamu tidak membebani server target. Untuk kebutuhan lebih lanjut seperti rotasi proxy atau user-agent acak, kamu bisa menambahkan middleware pihak ketiga seperti scrapy-user-agents.
Kesimpulan
Scrapy memberimu kerangka kerja lengkap untuk web scraping skala besar: spider yang terstruktur, selector CSS/XPath, pipeline data, dan kontrol penuh atas kecepatan crawling. Kamu kini bisa mengambil ribuan halaman dengan kode yang rapi dan mudah dirawat. Jika target kamu sederhana, mulailah dengan BeautifulSoup; jika halamannya membutuhkan JavaScript, beralihlah ke Playwright. Selamat mencoba, dan jangan lupa untuk selalu scraping secara bertanggung jawab!