Python ile Web Scraping

Web Scraping Nedir?

Web scraping (web kazıma), internet üzerindeki web sitelerinden otomatik olarak veri çıkarma ve toplama işlemidir. Bu süreç, bir program veya script kullanarak web sayfalarının HTML kodunu analiz eder, içindeki belirli verileri tanımlar ve bu verileri yapılandırılmış bir formatta (CSV, JSON, veritabanı vb.) saklar.

Web scraping, günümüzde veri bilimi, pazar araştırması, fiyat karşılaştırma, içerik toplama, haber takibi, sosyal medya analizi ve daha birçok alanda kullanılmaktadır. İnternet üzerindeki büyük miktardaki yapılandırılmamış veriyi, analiz edilebilir ve işlenebilir bir forma dönüştürmenin en etkili yollarından biridir.

Web scraping’in temel çalışma prensibi şu adımları içerir:

  • Web sayfasına HTTP isteği gönderme

  • HTML içeriğini alma

  • HTML’i ayrıştırma ve istenen verileri çıkarma

  • Verileri temizleme ve yapılandırma

  • Verileri depolama veya analiz etme

Python’un Web Scraping için Avantajları

Python, web scraping için en popüler ve tercih edilen programlama dillerinden biridir. Bunun çeşitli nedenleri vardır:

  • Kolay SözdizimiPython’un okunması ve yazılması kolay sözdizimi, web scraping gibi karmaşık işlemleri daha anlaşılır hale getirir.

  • Zengin Kütüphane EkosistemiPython, web scraping için özel olarak tasarlanmış BeautifulSoup, Scrapy, Selenium gibi güçlü kütüphanelere sahiptir.

  • Geniş Topluluk DesteğiPython’un büyük ve aktif bir topluluğu olduğundan, web scraping ile ilgili sorunlarınıza hızlıca çözüm bulabilirsiniz.

  • Veri İşleme Yetenekleri: Pandas, NumPy gibi veri işleme kütüphaneleri sayesinde, toplanan verileri kolayca işleyebilir ve analiz edebilirsiniz.

  • Cross-Platform UyumlulukPython, Windows, macOS ve Linux dahil olmak üzere tüm ana işletim sistemlerinde çalışabilir.

  • Otomatik Bellek YönetimiPython’un otomatik çöp toplama mekanizması, bellek yönetimini kolaylaştırır.

  • Asenkron İşleme DesteğiPython’un asyncio kütüphanesi, büyük ölçekli web scraping projelerinde eşzamanlı istek göndermeyi mümkün kılar.

Web Scraping Temel Kavramları

Web scraping’i etkili bir şekilde kullanabilmek için bazı temel kavramları anlamak önemlidir:

  • HTML (HyperText Markup Language): Web sayfalarının yapısını oluşturan işaretleme dilidir. Web scraping, bu HTML yapısını analiz ederek verileri çıkarır.

  • CSS Selektörleri: Web sayfasındaki belirli elementleri tanımlamak için kullanılan kalıplardır. Örneğin, div.content veya #main-header gibi.

  • XPath: XML belgelerindeki düğümleri seçmek için kullanılan bir dildir. HTML belgelerinde de elemanlara erişmek için kullanılabilir.

  • HTTP (HyperText Transfer Protocol): Web tarayıcıları ve sunucular arasındaki iletişimi sağlayan protokoldür. Web scraping yaparken, HTTP istekleri gönderip cevaplar alırsınız.

  • API (Application Programming Interface): Bazı web siteleri, verilerine erişmek için API’ler sunar. Eğer mevcutsa, web scraping yerine API kullanmak genellikle daha etik ve verimlidir.

  • Robots.txt: Web sitelerinin, botların hangi sayfaları ziyaret edebileceğini ve edemeyeceğini belirten dosyasıdır. Etik web scraping için bu kurallara uymak önemlidir.

  • User-Agent: HTTP isteğinde bulunan tarayıcı bilgisidir. Bazı siteler, belirli User-Agent’ları engelleyebilir.

Python Web Scraping Kütüphaneleri

Python’da web scraping için kullanılan başlıca kütüphaneler şunlardır:

Requests

Requests, HTTP istekleri göndermek için kullanılan basit ve kullanıcı dostu bir kütüphanedir. Web sayfalarının içeriğini indirmek için temel araçtır.

import requests

# Web sayfasına GET isteği gönderme
response = requests.get('https://www.example.com')

# Durum kodunu kontrol etme
if response.status_code == 200:
    # Sayfa içeriğini alma
    html_content = response.text
    # veya
    # binary_content = response.content
else:
    print(f"Hata: {response.status_code}")

# Başlıkları ve çerezleri kullanma
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
cookies = {'session_id': '123456'}
response = requests.get('https://www.example.com', headers=headers, cookies=cookies)

Requests kütüphanesinin diğer önemli özellikleri:

  • POST, PUT, DELETE gibi diğer HTTP metodlarını destekler

  • Otomatik JSON kodlama/çözme

  • Oturum yönetimi

  • Zamanaşımı ayarları

  • Proxy desteği

  • SSL doğrulama

BeautifulSoup

BeautifulSoup, HTML ve XML dosyalarını ayrıştırmak ve içeriğini çıkarmak için kullanılan güçlü bir kütüphanedir. Requests ile indirilen HTML içeriğini analiz etmek için sıklıkla kullanılır.

from bs4 import BeautifulSoup
import requests

# Web sayfasını indirme
url = 'https://www.example.com'
response = requests.get(url)
html_content = response.text

# BeautifulSoup nesnesi oluşturma
soup = BeautifulSoup(html_content, 'html.parser')

# Sayfa başlığını alma
title = soup.title.string
print(f"Sayfa başlığı: {title}")

# Belirli bir elementi seçme
header = soup.find('h1')
print(f"Başlık: {header.text}")

# Belirli bir class'a sahip tüm elementleri bulma
articles = soup.find_all('div', class_='article')
for article in articles:
    article_title = article.find('h2').text
    article_content = article.find('p').text
    print(f"Makale: {article_title}\nİçerik: {article_content}\n")

# CSS selektörleri kullanma
main_content = soup.select('div.main-content')

# Elementler arasında gezinme
parent = header.parent
siblings = header.next_siblings

BeautifulSoup, şu ayrıştırıcıları kullanabilir:

  • html.parser (Python’un dahili ayrıştırıcısı)

  • lxml (daha hızlı ve güçlü)

  • html5lib (en toleranslı ama en yavaş)

Scrapy

Scrapy, büyük ölçekli web scraping projeleri için tasarlanmış kapsamlı bir framework’tür. Sadece veri çıkarma değil, işleme, depolama ve dağıtım işlevleri de sunar.

# Spider örneği (spider.py dosyasında)
import scrapy

class NewsSpider(scrapy.Spider):
    name = 'news'
    start_urls = ['https://www.example-news.com']

    def parse(self, response):
        # Ana sayfadaki tüm haber bağlantılarını takip et
        for news_link in response.css('a.news-link::attr(href)').getall():
            yield response.follow(news_link, self.parse_news)

    def parse_news(self, response):
        # Her haber sayfasından veri çıkar
        yield {
            'title': response.css('h1.news-title::text').get(),
            'date': response.css('span.date::text').get(),
            'content': response.css('div.content p::text').getall(),
            'category': response.css('span.category::text').get(),
        }

Scrapy’yi çalıştırmak için komut satırını kullanabilirsiniz:

scrapy runspider spider.py -o news.json

Scrapy’nin avantajları:

  • Asenkron ve yüksek performanslı

  • Otomatik istek yönetimi

  • Yerleşik desenleri takip etme

  • Veri çıkarma kuralları (Item Pipelines)

  • Çoklu dışa aktarma formatları (JSON, CSV, XML)

  • Middleware desteği

  • Geniş eklenti ekosistemi

Selenium

Selenium, tarayıcı otomasyonu için kullanılan bir araçtır. JavaScript ile oluşturulan dinamik içeriği scrape etmek veya kullanıcı etkileşimi gerektiren sitelerde kullanılır.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time

# WebDriver ayarlama
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)

# Sayfayı ziyaret etme
driver.get('https://www.example.com')

# JavaScript'in yüklenmesi için bekleme
time.sleep(2)

# Dinamik olarak oluşturulan içeriği bulma
dynamic_elements = driver.find_elements(By.CLASS_NAME, 'dynamic-content')
for element in dynamic_elements:
    print(element.text)

# Etkileşim - Tıklama
button = driver.find_element(By.ID, 'load-more')
button.click()

# Formları doldurma
username_input = driver.find_element(By.NAME, 'username')
username_input.send_keys('myusername')
password_input = driver.find_element(By.NAME, 'password')
password_input.send_keys('mypassword')
login_button = driver.find_element(By.ID, 'login-button')
login_button.click()

# Ekran görüntüsü alma
driver.save_screenshot('screenshot.png')

# Tarayıcıyı kapatma
driver.quit()

Selenium’un kullanım alanları:

  • JavaScript ile render edilen SPA (Single Page Applications)

  • Kullanıcı girişi gerektiren siteler

  • Sonsuz kaydırma veya “Daha Fazla Yükle” butonları olan sayfalar

  • CAPTCHA çözümü gerektiren siteler

  • Karmaşık kullanıcı etkileşimleri

LXML

LXML, XML ve HTML belgelerini işlemek için hızlı ve esnek bir kütüphanedir. XPath sorguları için özellikle güçlüdür.

import requests
from lxml import html

# Sayfa içeriğini alma
response = requests.get('https://www.example.com')
tree = html.fromstring(response.content)

# XPath ile elementleri seçme
titles = tree.xpath('//h2[@class="title"]/text()')
links = tree.xpath('//a[@class="link"]/@href')

# Sonuçları yazdırma
for title, link in zip(titles, links):
    print(f"Başlık: {title}, Bağlantı: {link}")

LXML’in avantajları:

  • Çok hızlı ayrıştırma

  • Düşük bellek kullanımı

  • Güçlü XPath desteği

  • XSLT dönüşümleri

  • XML şema doğrulama

Pandas

Pandas, veri analizi için kullanılan bir kütüphanedir, ancak read_html() fonksiyonu ile web sayfalarındaki tabloları doğrudan DataFrame’lere dönüştürebilir.

import pandas as pd

# URL'deki tüm tabloları oku
tables = pd.read_html('https://www.example.com/table-page')

# İlk tabloyu al
df = tables[0]

# Veriyi işle
print(df.head())
print(df.describe())

# CSV'ye kaydet
df.to_csv('data.csv', index=False)

Temel Web Scraping Örneği

Aşağıda, Python ile basit bir web scraping örneği bulunmaktadır. Bu örnekte, bir haber sitesinden en son haberleri çekiyoruz:

import requests
from bs4 import BeautifulSoup
import csv
from datetime import datetime

def scrape_news():
    # URL ve kullanıcı ajanı tanımlama
    url = 'https://example-news.com'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }
    
    # Sayfayı indirme
    print(f"{url} indiriliyor...")
    response = requests.get(url, headers=headers)
    
    # Hata kontrolü
    if response.status_code != 200:
        print(f"Hata: {response.status_code}")
        return []
    
    # HTML içeriğini ayrıştırma
    soup = BeautifulSoup(response.content, 'html.parser')
    
    # Haber elementlerini bulma
    news_elements = soup.select('div.news-item')
    
    # Sonuçları depolayacak liste
    news_data = []
    
    # Her haber öğesini işleme
    for news in news_elements:
        try:
            # Gerekli verileri çıkarma
            title = news.select_one('h2.title').text.strip()
            summary = news.select_one('p.summary').text.strip()
            link = news.select_one('a.read-more')['href']
            date_str = news.select_one('span.date').text.strip()
            category = news.select_one('span.category').text.strip()
            
            # Göreli URL'i mutlak URL'e dönüştürme
            if link.startswith('/'):
                link = f"{url}{link}"
            
            # Veriyi listeye ekleme
            news_data.append({
                'title': title,
                'summary': summary,
                'link': link,
                'date': date_str,
                'category': category
            })
        except Exception as e:
            print(f"Haber işlenirken hata: {e}")
    
    print(f"Toplam {len(news_data)} haber bulundu.")
    return news_data

def save_to_csv(data, filename):
    # CSV dosyasına kaydetme
    fieldnames = ['title', 'summary', 'link', 'date', 'category']
    
    with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(data)
    
    print(f"Veriler {filename} dosyasına kaydedildi.")

if __name__ == "__main__":
    # Haber verilerini çekme
    news_data = scrape_news()
    
    if news_data:
        # Dosya adını tarihle oluşturma
        current_date = datetime.now().strftime("%Y-%m-%d")
        filename = f"news_{current_date}.csv"
        
        # Verileri CSV'ye kaydetme
        save_to_csv(news_data, filename)

Bu kod şunları yapar:

  • Belirtilen URL’den haber sayfasını indirir

  • BeautifulSoup ile HTML içeriğini ayrıştırır

  • CSS selektörleri kullanarak haber öğelerini bulur

  • Her haberden başlık, özet, bağlantı, tarih ve kategori bilgilerini çıkarır

  • Verileri bir CSV dosyasına kaydeder

İleri Seviye Teknikler

AJAX ve JavaScript İçeriği Scraping

Modern web siteleri genellikle AJAX ve JavaScript kullanarak içeriklerini dinamik olarak yükler. Bu tür içeriği scrape etmek için birkaç yaklaşım vardır:

1. Selenium ile Tam Tarayıcı Simulasyonu

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get('https://example.com/dynamic-content')

# Belirli bir elementin yüklenmesini bekle
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, 'dynamic-content')))

# Sayfayı aşağı kaydır (Sonsuz kaydırma için)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

# Sayfa kaynağını al (JavaScript çalıştıktan sonra)
html_content = driver.page_source

# İşlemleri tamamlama
driver.quit()

2. API İsteklerini Analiz Etme

Birçok site, verilerini API çağrıları üzerinden yükler. Bu API’leri taklit ederek veri çekebilirsiniz:

import requests
import json

# API endpointine istek gönderme
api_url = 'https://example.com/api/products?page=1&limit=50'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Referer': 'https://example.com/products',
    'X-Requested-With': 'XMLHttpRequest'
}

response = requests.get(api_url, headers=headers)
data = response.json()

# JSON verisini işleme
for product in data['products']:
    print(f"Ürün: {product['name']}, Fiyat: {product['price']}")

Kimlik Doğrulama Gerektiren Siteler

Oturum açma gerektiren sitelerde veri çekmek için birkaç yöntem kullanabilirsiniz:

1. Requests ile Oturum Yönetimi

import requests

# Oturum oluşturma
session = requests.Session()

# Giriş verilerini hazırlama
login_url = 'https://example.com/login'
login_data = {
    'username': 'your_username',
    'password': 'your_password',
    'submit': 'Login'
}

# Giriş yapma
response = session.post(login_url, data=login_data)

# Giriş başarılı mı kontrol etme
if 'Welcome' in response.text:
    print("Giriş başarılı!")
    
    # Artık oturum açıldı, korumalı sayfaları ziyaret edebilirsiniz
    protected_page = session.get('https://example.com/protected-page')
    # İçeriği işleme...
else:
    print("Giriş başarısız!")

2. Selenium ile Otomatik Form Doldurma

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://example.com/login')

# Form alanlarını doldurma
username_field = driver.find_element(By.NAME, 'username')
password_field = driver.find_element(By.NAME, 'password')
submit_button = driver.find_element(By.ID, 'login-button')

username_field.send_keys('your_username')
password_field.send_keys('your_password')
submit_button.click()

# Giriş sonrası korumalı içeriği scrape etme
driver.get('https://example.com/protected-page')
protected_content = driver.find_element(By.ID, 'protected-content').text

Anti-Bot Önlemlerini Aşma

Birçok web sitesi, bot trafiğini engellemek için çeşitli önlemler alır. Bu önlemlerle başa çıkmak için:

1. User-Agent Rotasyonu

import requests
import random

# User-Agent listesi
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0'
]

# Rastgele User-Agent seçme
headers = {
    'User-Agent': random.choice(user_agents)
}

response = requests.get('https://example.com', headers=headers)

2. Proxy Rotasyonu

import requests

# Proxy listesi
proxies_list = [
    {'http': 'http://proxy1.example.com:8080'},
    {'http': 'http://proxy2.example.com:8080'},
    {'http': 'http://proxy3.example.com:8080'}
]

# Her proxy'yi deneme
for proxy in proxies_list:
    try:
        response = requests.get('https://example.com', proxies=proxy, timeout=5)
        if response.status_code == 200:
            print(f"Başarılı: {proxy}")
            # İçeriği işleme...
            break
    except Exception as e:
        print(f"Hata: {proxy} - {e}")

3. İstek Aralıklarını Ayarlama

import requests
import time
import random

urls = ['https://example.com/page1', 'https://example.com/page2', 'https://example.com/page3']

for url in urls:
    # İstek gönderme
    response = requests.get(url)
    print(f"Status: {response.status_code}, URL: {url}")
    
    # Rastgele bekleme (2-5 saniye)
    delay = random.uniform(2, 5)
    print(f"{delay:.2f} saniye bekleniyor...")
    time.sleep(delay)

Veri Depolama ve İşleme

Web scraping ile toplanan verileri çeşitli formatlarda depolayabilir ve işleyebilirsiniz:

CSV Dosyaları

import csv

data = [
    {'name': 'Ürün 1', 'price': 100, 'stock': 50},
    {'name': 'Ürün 2', 'price': 200, 'stock': 30},
    {'name': 'Ürün 3', 'price': 150, 'stock': 0}
]

with open('products.csv', 'w', newline='', encoding='utf-8') as csvfile:
    fieldnames = ['name', 'price', 'stock']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    
    writer.writeheader()
    writer.writerows(data)


comments powered by Disqus