Merhaba Python geliştiricileri! 2025'te web scraping dünyası hızla evriliyor. JavaScript ağır siteler, anti-bot sistemleri ve büyük veri hacimleri artık standart. Geleneksel araçlar gibi Selenium veya Requests yetersiz kalıyor: Selenium yavaş ve bellek canavarı, Scrapy ise dinamik içeriklerde zorlanıyor. İşte burada Playwright devreye giriyor – Microsoft'un açık kaynaklı browser otomasyon kütüphanesi, async desteğiyle 5-10 kat daha hızlı scraping sunuyor.

Bu makalede, Playwright'ı async modda kullanarak en hızlı scraping yöntemini anlatacağım. Neden en iyi? Performans testlerinde Playwright, Selenium'dan %35-57 daha hızlı (sayfa navigasyonu 1.8s vs 2.7s), ve Scrapy'den %20-30 daha verimli dinamik sitelerde. Async ile birden fazla sayfayı paralel scrape ederek zamanı %70 kısaltabilirsiniz.

Hadi başlayalım: Kurulum, temel async scraping, performans ipuçları ve tam örnek kod!


Neden Playwright + Async 2025'in En Hızlı Yöntemi?

  • Hız: Async API ile I/O-bound işlemlerde (sayfa yükleme) paralel çalışma. Selenium'un aksine, browser context'leri hafif (50-100MB RAM/sayfa).
  • Güvenilirlik: Auto-wait mekanizması (waitForLoadState, waitForSelector) ile flaky scraping yok. Dinamik JS siteleri için ideal.
  • Cross-Browser: Chromium, Firefox, WebKit – tek API ile hepsi.
  • Anti-Bot Kaçınma: Proxy entegrasyonu, user-agent rotation ve resource blocking (resim/CSS bloklama) ile ban riski düşük.


Kurulum (2 Dakika!)

Async için ekstra paket yok – Python'un built-in asyncio yeterli.

Playwright'ı pip ile yükleyin ve browser'ları kurun:


pip install playwright

playwright install # Chromium, Firefox, WebKit'i indirir



Paralel Çoklu Sayfa Scraping (En Hızlı Yöntem)

Gerçek güç: Birden fazla URL'yi paralel scrape et. Semaphore ile concurrency'yi sınırlayın (sunucuyu spam'lememek için).

import asyncio
from playwright.async_api import async_playwright
from typing import List

async def scrape_url(browser, url: str, semaphore: asyncio.Semaphore):
  """Tek URL'yi scrape et, semaphore ile limitli."""
  async with semaphore:
    c browser.new_context(
      viewport={'width': 1920, 'height': 1080},
      user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' # User-agent rotation
    )
    page = await context.new_page()
     
    # Resource blocking: Resim ve CSS'leri blokla, hızı %50 artır
    await page.route('**/*.{png,jpg,jpeg,gif,css}', lambda route: route.abort())
     
    await page.goto(url, wait_until='networkidle', timeout=30000)
    title = await page.title()
    links = await page.locator('a[href]').all_text_contents() # Tüm linkler
     
    await context.close()
    return {'url': url, 'title': title, 'link_count': len(links)}

async def scrape_multiple(urls: List[str], max_concurrent: int = 5):
  """Paralel scraping."""
  async with async_playwright() as p:
    browser = await p.chromium.launch(headless=True)
    semaphore = asyncio.Semaphore(max_concurrent)
    tasks = [scrape_url(browser, url, semaphore) for url in urls]
    results = await asyncio.gather(*tasks, return_excepti>
    await browser.close()
    return [r for r in results if not isinstance(r, Exception)]

# Örnek kullanım
async def main():
  urls = [
    'https://example.com',
    'https://httpbin.org/html',
    'https://quotes.toscrape.com/' # Test sitesi
  ]
  results = await scrape_multiple(urls)
  for result in results:
    print(result)

asyncio.run(main())



Çıktı Örneği:


{'url': 'https://example.com', 'title': 'Example Domain', 'link_count': 2}
{'url': 'https://httpbin.org/html', 'title': 'httpbin.org', 'link_count': 15}
{'url': 'https://quotes.toscrape.com/', 'title': 'Quotes to Scrape', 'link_count': 10}

Performans İpuçları 2025 İçin

  1. Headless + Resource Blocking: Resim/CSS bloklayın, yüklemeyi %40 hızlandırır.
  2. Wait Stratejileri:wait_until='networkidle' veya wait_for_selector kullanın – fixed sleep yok!
  3. Proxy Entegrasyonu: Ban yememek için rotating proxy ekleyin:


browser = await p.chromium.launch(proxy={'server': 'http://proxy-server:port'})

4.Retry Mekanizması: Exponential backoff ile hataları yönetin:

import time
for attempt in range(3):
  try:
    await page.goto(url)
    break
  except:
    await asyncio.sleep(2 ** attempt) # 1s, 2s, 4s