Belajar Scrapling - Performance Optimization
Episode 18 of 23

Belajar Scrapling - Performance Optimization

Mengoptimalkan performa scraper Scrapling: benchmark parser (Scrapling vs lxml vs Parsel vs Selectolax vs PyQuery), strategi memilih fetcher yang tepat, serta teknik memory dan speed seperti reuse tree, membatasi payload, dan seleksi batch.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 17 kalian belajar spider lanjutan: pause/resume lewat checkpoint, state persistence, dan real-time stats untuk crawl ribuan halaman. Semakin besar scale crawl, semakin terasa satu hal: performa. Satu detik yang dihemat per halaman akan terakumulasi jadi jam penghematan saat kalian crawl 10 ribu halaman. Episode 18 ini fokus ke optimasi performa.

Roadmap episode ini: pertama kita membandingkan parser Scrapling dengan alternatif lain lewat benchmark, lalu membahas strategi memilih fetcher yang tepat sesuai kebutuhan, dan terakhir menutup dengan teknik memory dan speed — reuse tree, membatasi payload, dan optimasi seleksi batch.

Mengapa Performa Scraper Kritis

Web scraping yang lambat bukan sekadar masalah kenyamanan — ia biaya. Semakin lama satu halaman diproses, semakin banyak resource yang terpakai, semakin besar risiko timeout, dan semakin kecil throughput data yang bisa dikumpulkan dalam jendela waktu tertentu.

Ada tiga sumber pemborosan yang paling umum:

  • Parsing berulang — konten HTML yang sama diparse berkali-kali padahal bisa dipakai ulang.
  • Fetcher yang terlalu berat — menggunakan browser untuk halaman statis yang seharusnya cukup lewat HTTP biasa.
  • Seleksi boros — query yang berulang, selektor yang terlalu umum, dan iterasi yang tidak perlu.

Prinsip utama optimasi di episode ini sederhana: jangan buang waktu pada apa yang tidak perlu. Pilih parser tercepat untuk kerjaan kalian, pilih fetcher paling ringan yang masih bisa menembus proteksi halaman, dan jangan parse ulang apa yang sudah ada di tangan.

Benchmark Parser: Scrapling vs Kompetitor

Parser adalah lapisan yang paling sering jadi bottleneck. Adaptor Scrapling dibangun di atas lxml (pembungkus C libxml2), sehingga kecepatannya dekat dengan lxml mentah — dan jauh meninggalkan parser Python murni. Perbandingan cepatnya:

ParserBasisKecepatanCatatan
Scrapling Adaptorlxml + optimasi ScraplingSangat cepatSelector kaya, self-healing
lxmlC libxml2Sangat cepatAPI dasar, tanpa helper modern
Parsellxml, gaya ScrapyCepatNyaman jika terbiasa Scrapy
SelectolaxRust (Lexbor)Tercepat di parsing murniFitur seleksi terbatas
PyQuerylxml, gaya jQueryCepatGaya sintaks jQuery
BeautifulSoupPython murniLambat (patokan)Mudah, banyak tutorial

Untuk memvalidasi sendiri, kalian bisa memakai timeit seperti contoh berikut:

PythonBenchmark sederhana: parse + seleksi
import timeit
 
from scrapling import Fetcher
from lxml import html
 
url = "https://quotes.toscrape.com/"
raw = Fetcher().get(url).body
 
 
def scrapling_path():
    page = Fetcher().get(url)
    return len(page.css(".quote .text::text").getall())
 
 
def lxml_path():
    tree = html.fromstring(raw)
    return len(tree.xpath('//div[contains(@class,"quote")]//span[contains(@class,"text")]/text()'))
 
 
scrapling_time = timeit.timeit(scrapling_path, number=20)
lxml_time = timeit.timeit(lxml_path, number=20)
print(f"Scrapling: {scrapling_time:.3f}s")
print(f"lxml: {lxml_time:.3f}s")

Info

Angka benchmark sangat bergantung pada hardware, versi library, dan isi halaman. Jangan mengambil angka orang lain sebagai kebenaran mutlak — jalankan benchmark di mesin kalian sendiri sebelum membuat keputusan arsitektur.

Poin yang perlu diingat: Scrapling hampir selalu kalah tipis dari Selectolax dalam parsing murni, tapi menang telak dalam produktivitas karena css, xpath, find_by_text, find_by_regex, dan auto_match ada di satu API yang konsisten. Untuk produktivitas, selisih mikro-detik per parse sering tidak sebanding dengan selisih jam debugging.

Strategi Memilih Fetcher

Setelah parser, fetcher adalah penentu performa terbesar. Aturan emasnya: gunakan fetcher paling ringan yang masih berhasil. Hanya eskalasi ke lapisan lebih berat ketika halaman benar-benar membutuhkannya.

KebutuhanFetcher
Halaman statis, proteksi ringanFetcher
Banyak halaman paralelAsyncFetcher
Halaman JavaScript/SPAPlayWrightFetcher
Anti-bot berat, Cloudflare/TurnstileStealthyFetcher

Contoh eskalasi yang benar: coba Fetcher dulu. Jika hasilnya kosong atau diblokir, baru naik ke PlayWrightFetcher untuk render JS. Jika proteksinya anti-bot, barulah StealthyFetcher. Urutan ini memastikan mayoritas request kalian berjalan di jalur tercepat.

PythonPola eskalasi fetcher yang efisien
from scrapling import Fetcher
 
page = Fetcher().get("https://shop.example.com/products")
 
if not page.css(".product"):
    from scrapling import PlayWrightFetcher
 
    page = PlayWrightFetcher().get("https://shop.example.com/products")
 
print(len(page.css(".product")))

Reuse Tree: Parsing Sekali, Pakai Banyak

Kesalahan paling umum kedua setelah salah pilih fetcher adalah memparse ulang. Setiap Fetcher().get(url) melakukan request jaringan plus parsing penuh. Jika kalian butuh lima seleksi berbeda dari halaman yang sama, tidak perlu lima request.

PythonSatu fetch, banyak seleksi
from scrapling import Fetcher
 
page = Fetcher().get("https://quotes.toscrape.com/")
 
for n in range(5):
    titles = page.css(".quote .text::text").getall()
    authors = page.css(".quote .author::text").getall()
    print(len(titles), len(authors))

Kode di atas memakai objek Adaptor yang sama lima kali tanpa request tambahan. Tree lxml di dalamnya sudah terbuild, sehingga setiap seleksi berikutnya hanya traversal di memori — puluhan kali lebih cepat daripada request baru. Simpan Adaptor selama masih dibutuhkan, dan biarkan garbage collector bekerja setelahnya.

Batasi Payload

Semakin besar HTML yang diproses, semakin lama parsing dan semakin banyak memori. Strategi membatasi payload:

  • Pilih halaman yang tepat — jika data tersedia via API JSON, fetch API-nya dengan Fetcher daripada memparsing HTML.
  • Buang bagian yang tidak perlu — tag script, style, dan noscript biasanya tidak relevan untuk ekstraksi teks.
  • Gunakan selektor spesifik — selektor yang menyempitkan scope lebih dulu (misal masuk ke body lalu elemen target) mengurangi node yang ditelusuri.

Untuk teks bersih, get_all_text bisa dikonfigurasi membuang tag yang tidak perlu sekaligus:

PythonEkstrak teks bersih, buang tag berat
text = page.get_all_text(
    separator="\n",
    ignore_tags=("script", "style", "noscript"),
)

Pada halaman raksasa (misal dokumen SPARQL atau log), pertimbangkan juga mengambil hanya sebagian konten via range request dari server, atau membagi proses menjadi beberapa batch kecil agar memori puncak tetap terkendali.

Optimasi Seleksi Batch

Polanya sama untuk seleksi: ambil semua dulu, baru proses. Hindari memanggil seleksi dari root berulang-ulang di dalam loop.

PythonSebelum: query root di dalam loop
for i in range(50):
    titles = page.css(".product .product-title::text").getall()
PythonSesudah: ambil sekali, proses per item
cards = page.css(".product")
rows = [
    {
        "title": card.css(".product-title::text").get(),
        "price": card.css(".price::text").get(),
    }
    for card in cards
]

Versi kedua memanggil seleksi root sekali saja, lalu melakukan chaining di dalam scope setiap card — jauh lebih murah karena scope-nya sudah dipersempit. Kombinasikan juga selektor yang sejenis dengan koma (misal h1, h2, h3) dan manfaatkan find_all dengan filter attribute dictionary untuk kondisi yang kompleks. Seleksi batch yang rapi bukan hanya cepat — hasilnya juga langsung jadi dataset terstruktur yang siap diolah.

Penutup

Episode ini menutup Fase 5 — Advanced Topics, Scaling & Optimization — di sisi performa. Kalian sudah tahu cara membandingkan parser, memilih fetcher paling ringan yang cukup, memakai ulang tree, membatasi payload, dan mengeksekusi seleksi secara batch. Semua ini bekerja bersama di produksi untuk menekan biaya dan mempercepat throughput.

Inti yang harus dibawa pulang:

  • Parser Scrapling mendekati kecepatan lxml mentah dengan produktivitas jauh lebih tinggi; benchmark di mesin sendiri sebelum memutuskan.
  • Pilih fetcher paling ringan yang cukup — naik level hanya saat halaman menuntut.
  • Jangan parse ulang — simpan dan pakai ulang objek Adaptor.
  • Batasi payload sejak awal — pilih halaman yang tepat dan buang tag yang tidak relevan.
  • Seleksi batch lebih baik daripada loop query — ambil semua dulu, lalu proses per item.

Di episode 19, kita berbelok ke arah baru yang memanfaatkan model: Integrasi AI & LLM Extractionscrapling[ai], WebScrapingAI, MCP server untuk AI agent, dan LLM-led parsing dan validation. Sampai jumpa!