Python ile TripAdvisor Kazıma Rehberi (Engellenmeden)

Son güncelleme: April 17, 2026
Python ile TripAdvisor Kazıma Rehberi (Engellenmeden)

Geçen hafta TripAdvisor üzerinden üç Avrupa şehrindeki yaklaşık 200 tesisin otel puanlarını ve yorum sayılarını çekmeye çalıştım. İlk denemem — varsayılan başlıklarla çalışan basit bir requests.get() — her istekte dümdüz 403 Forbidden döndürdü. Tek bir işe yarar veri baytı bile alamadım.

TripAdvisor, seyahat alanındaki en zengin açık veri kaynaklarından biri: 1 milyardan fazla yorum, 8 milyonu aşan işletme kaydı ve ayda yaklaşık 460 milyon tekil ziyaretçi. Yıllık seyahat harcamalarının $60 milyar üzerindeki kısmını etkiliyor. Peki bu veriyi programatik olarak almak? İşte işin zor tarafı burada başlıyor. TripAdvisor; DataDome bot tespiti, Cloudflare WAF, TLS fingerprinting ve JavaScript zorlukları gibi katmanlı bir savunma sistemi kullanıyor ve çoğu acemi kazıma girişimini daha ilk adımda durduruyor. Bu rehber, keşke elimde olsaydı dediğim tek kaynak: üç Python kazıma yaklaşımının kafa kafaya karşılaştırması (artı kod yazmadan kullanılabilecek bir seçenek), her yöntem için tam kod, yapılandırılmış anti-bot sorun giderme bölümü ve oteller, restoranlar ve turistik yerler genelinde yeniden kullanılabilecek kalıplar. İster Python’a yeni başlamış olun ister deneyimli bir geliştirici, bu rehber size boşuna yaşanmış birçok 403 hatasını kurtaracak.

Kod Yazmak İstemiyor musunuz? TripAdvisor’ı Kolay Yoldan Kazıyın

Bir şeyi en baştan açık söyleyeyim. "Python ile TripAdvisor kazıma" diye arayanların büyük kısmı aslında kod yazmaya meraklı değil. Onların istediği şey, hızlıca tabloya düşen veri — otel adları, puanlar, yorum sayıları, fiyatlar. Eğer siz de onlardan biriyseniz, çok daha kısa bir yol var.

Thunderbit, bizim geliştirdiğimiz yapay zekâ destekli bir Chrome uzantısı; herhangi bir TripAdvisor sayfasını okuyabilir ve hangi sütunların çıkarılması gerektiğini otomatik olarak önerebilir. İş akışı gerçekten iki tıklama kadar basit:

  1. Bir TripAdvisor listeleme sayfasını açın (ör. "Paris’teki Oteller" sonuçları).
  2. Thunderbit kenar çubuğunda "AI Suggest Fields" seçeneğine tıklayın. Yapay zekâ sayfayı tarar ve Otel Adı, Puan, Yorum Sayısı, Fiyat ve Konum gibi sütunlar önerir.
  3. "Scrape" butonuna tıklayın. Thunderbit sayfadaki tüm listelemelerden veriyi çeker — daha fazla sonuç gerekiyorsa sayfalama işlemini de otomatik yapar.
  4. Veriyi Excel, Google Sheets, Airtable veya Notion’a aktarın. Tüm planlarda dışa aktarma ücretsizdir.

Thunderbit, herhangi bir yapılandırma değişikliği yapmadan oteller, restoranlar ve turistik yerler arasında çalışır — yapay zekâ sayfadaki içeriğe göre kendini uyarlar. Sayfalı sonuçlarda "Next" düğmelerini ve sonsuz kaydırmayı otomatik algılar. Üstelik gerçek Chrome tarayıcınızın içinde çalıştığı için oturum çerezlerinizi ve tarayıcı fingerprint’inizi kullanır; bu da bot tespitine karşı doğal bir avantaj sağlar.

Bunu Thunderbit Chrome Extension ile deneyebilirsiniz — ücretsiz katman ayda 6 sayfa verir; iş akışını test etmek için fazlasıyla yeterli.

Programatik kontrol, özel ayrıştırma mantığı ya da 10.000+ sayfa kazıma planınız varsa, Python doğru seçimdir. Okumaya devam edin.

Neden TripAdvisor’ı Python ile Kazımalısınız?

TripAdvisor verisinin doğrudan ve ölçülebilir bir iş etkisi vardır. Cornell University tarafından yapılan bir çalışmada, bir otelin 100 puanlık Global Review Index değerinde 1 puanlık artışın, ortalama günlük oda fiyatında %0,89 ve müsait oda başına gelirde %1,42 artışa yol açtığı bulundu. ScienceDirect üzerindeki başka bir çalışma ise TripAdvisor puanında dışsal 1 yıldızlık artışın, ortalama bir otel için yıllık gelire 55.000–75.000 dolar eklediğini gösterdi. Yorumlar sadece gösteriş metriği değildir — doğrudan gelir üretirler.

Farklı ekipler TripAdvisor verisini şu şekilde kullanır:

Kullanım SenaryosuKimler İçin FaydalıGerekli Veri
Otel rakip analiziOtel zincirleri, gelir yöneticileriPuanlar, fiyatlar, yorum hacmi, olanaklar
Restoran pazar araştırmasıRestoran grupları, gıda markalarıMutfak türleri, fiyat aralıkları, yorum duyarlılığı
Turistik yer trend takibiTur operatörleri, turizm kurullarıPopülerlik sıralamaları, mevsimsel desenler
Duygu analiziAraştırmacılar, veri analistleriTam yorum metni, yıldız puanları, tarihler
Lead generationSatış ekipleri, seyahat acenteleriİşletme adları, iletişim bilgileri, konumlar

Peki neden özellikle Python? Üç neden var. Birincisi, ekosistem: BeautifulSoup, Selenium, Playwright, Scrapy, httpx, pandas — Python’ın kazıma ve veri analizi kütüphaneleri diğer dillerdeki muadillerine göre daha olgun. İkincisi, web kazıma geliştiricilerinin %71,7’si Python kullanıyor; bu da daha fazla topluluk desteği, daha çok StackOverflow cevabı ve daha güncel rehberler demek. Üçüncüsü, iş akışı avantajı: BeautifulSoup ile kazıyıp pandas ile temizleyebilir, Hugging Face Transformers ile duygu analizi yapabilir ve panolar oluşturabilirsiniz — hepsi tek dilde. Bağlam değiştirme derdi yok.

TripAdvisor’ı Python ile Kazımanın Üç Yolu (Karşılaştırmalı)

Rakip rehberlerin çoğu tek bir yöntemi seçip onun üzerinden gider. Oysa siz kod yazmadan önce karar vermeye çalışıyorsanız bunun pek faydası yok. İşte keşke biri bana önceden verseydi dediğim karşılaştırma tablosu:

YaklaşımHızJS DesteğiBot Engeline DirençKarmaşıklıkEn Uygun Olduğu Durum
requests + BeautifulSoup⚡ Hızlı (~120–200 sayfa/dk ham)❌ Yok⚠️ DüşükKolayStatik listeleme sayfaları, küçük ölçekli projeler
Selenium / Headless Tarayıcı🐢 Yavaş (~8–20 sayfa/dk)✅ Tam⚠️ OrtaOrtaDinamik içerik, "Read more" tıklamaları, çerez banner’ları
Gizli JSON / GraphQL API⚡⚡ En hızlı (~200–600 sayfa/dk ham)N/A✅ Daha yüksekZorBüyük ölçekli yorum/otel çıkarımı
Kod yazmadan (Thunderbit)⚡ Hızlı✅ Yerleşik✅ YerleşikEn kolayKod yazmayanlar, hızlı tek seferlik dışa aktarımlar

Birkaç önemli not var. Bu ham hızlar teoriktir — TripAdvisor’ın hız limitleri (IP başına yaklaşık dakikada 10–15 istek) gerçek verimi, yaklaşım ne olursa olsun, kabaca IP başına dakikada 10 sayfaya indirir. Gizli JSON yöntemi, tek istekte daha fazla veri aldığı için toplam istek sayısını azaltır ve hız limitine daha az maruz kalır. Selenium, gerçek dünyadaki ölçümlerde istek tabanlı yöntemlerden yaklaşık 5 kat yavaştır; ancak butonlara tıklamanız veya JavaScript render etmeniz gerekiyorsa tek seçenektir.

Bu rehberin geri kalanı, üç Python yönteminin tamamını tam kodla anlatıyor. Durumunuza uyanı seçin ya da yöntemleri birleştirin (ben çoğu zaman listeleme sayfalarında requests+BS4, detay sayfalarında ise gizli JSON kullanıyorum).

Python Ortamınızı Hazırlayın

Başlamadan önce ortamı hazırlayalım. Python 3.10+ gerekiyor (ben 3.12 veya 3.13 öneriyorum — büyük paketlerin hepsi sorunsuz destekliyor).

Hepsini tek seferde kurun:

pip install requests beautifulsoup4 selenium httpx parsel pandas curl-cffi

Paket notları:

  • requests (2.33.1) — HTTP istekleri, Python 3.10+ gerekir
  • beautifulsoup4 (4.14.3) — HTML ayrıştırma
  • selenium (4.43.0) — Tarayıcı otomasyonu, Python 3.10+ gerekir
  • httpx (0.28.1) — Async HTTP istemcisi
  • parsel (1.11.0) — CSS/XPath seçiciler (BS4’ten daha hafif)
  • pandas (3.0.2) — Veri dışa aktarma, Python 3.11+ gerekir
  • curl_cffi (0.15.0) — TLS fingerprint taklidi (Cloudflare aşmak için kritik)

ChromeDriver: Selenium kullanıyorsanız güzel haber — Selenium 4.6+ ile Selenium Manager, doğru ChromeDriver ikili dosyasını otomatik indirip önbelleğe alır. Elle kurulum gerekmez. Sürüm eşleştirmesini dinamik yaptığı için Chrome sürüm uyumsuzluğu derdi yaşamazsınız.

Sanal ortam (önerilir):

python -m venv tripadvisor-scraper
source tripadvisor-scraper/bin/activate  # macOS/Linux
tripadvisor-scraper\Scripts\activate     # Windows

Yöntem 1: Requests ve BeautifulSoup ile TripAdvisor Kazıma

Bu en basit yöntemdir. İhtiyacınız olan verinin statik HTML içinde bulunduğu listeleme sayfaları için çok iyi çalışır (otel arama sonuçları, restoran listeleri). Tarayıcı yok, JavaScript render yok, minimum kaynak kullanımı.

TripAdvisor URL Kalıplarını Anlamak

TripAdvisor URL’leri kategoriye göre öngörülebilir kalıplar izler:

  • Oteller: https://www.tripadvisor.com/Hotels-g{locationId}-{Location_Name}-Hotels.html
  • Restoranlar: https://www.tripadvisor.com/Restaurants-g{locationId}-{Location_Name}.html
  • Turistik yerler: https://www.tripadvisor.com/Attractions-g{locationId}-Activities-{Location_Name}.html

Sayfalama, URL’ye eklenen oa (offset anchors) parametresiyle yapılır. Her sayfada 30 sonuç gösterilir:

    1. sayfa: temel URL (oa parametresi yok)
    1. sayfa: Hotels-g187768-oa30-Italy-Hotels.html
    1. sayfa: Hotels-g187768-oa60-Italy-Hotels.html

Yorum sayfalarında ofset parametresi or olur ve 10’ar 10’ar artar:

    1. sayfa: Reviews-or0-Hotel_Name.html
    1. sayfa: Reviews-or10-Hotel_Name.html

Yorumları tüm dillerde almak için URL’ye ?filterLang=ALL ekleyin.

Gerçekçi Başlıklarla İstek Gönderme

TripAdvisor başlıkları oldukça agresif kontrol eder. Varsayılan Python başlıklarıyla gelen bir istek anında engellenir. Gerçek bir Chrome tarayıcısını taklit etmeniz gerekir:

import requests
import time
import random

session = requests.Session()

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Referer": "https://www.tripadvisor.com/",
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "none",
    "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
    "Sec-CH-UA-Mobile": "?0",
    "Sec-CH-UA-Platform": '"Windows"',
}

session.headers.update(headers)

url = "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"
response = session.get(url)

print(f"Status: {response.status_code}")
print(f"İçerik uzunluğu: {len(response.text)} karakter")

Kritik detay: TripAdvisor, User-Agent ile Sec-CH-UA istemci ipuçlarının birbiriyle tutarlı olmasını doğrular. User-Agent içinde Chrome 135 yazıp Sec-CH-UA içinde Chrome 120 derseniz, işaretlenirsiniz. Her zaman tek tek başlıkları değil, tam başlık setlerini birlikte döndürün.

BeautifulSoup ile Listelemeleri Ayrıştırma

Başarılı bir yanıt aldıktan sonra veriyi BeautifulSoup ile çıkarabilirsiniz. TripAdvisor, sık değişen CSS sınıf adları yerine daha kararlı olan data-automation ve data-test-attribute niteliklerini kullanır:

from bs4 import BeautifulSoup

soup = BeautifulSoup(response.text, "html.parser")

# Tüm otel kartlarını bul
cards = soup.select('div[data-test-attribute="location-results-card"]')

hotels = []
for card in cards:
    # Otel adı
    title_el = card.select_one('div[data-automation="hotel-card-title"]')
    name = title_el.get_text(strip=True) if title_el else None

    # Detay sayfası bağlantısı
    link_el = card.select_one('div[data-automation="hotel-card-title"] a')
    link = "https://www.tripadvisor.com" + link_el["href"] if link_el else None

    # Puan
    rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
    rating = rating_el.get_text(strip=True) if rating_el else None

    # Yorum sayısı
    review_el = card.select_one('[data-automation="bubbleReviewCount"]')
    review_count = review_el.get_text(strip=True).replace(",", "").split()[0] if review_el else None

    hotels.append({
        "name": name,
        "rating": rating,
        "review_count": review_count,
        "url": link,
    })

print(f"Bu sayfada {len(hotels)} otel bulundu")
for h in hotels[:3]:
    print(h)

Seçiciler hakkında not: TripAdvisor, her site güncellemesinde değişen obfuscation’lı CSS sınıfları (FGwzt, yyzcQ gibi) kullanır. data-automation ve data-test-target nitelikleri çok daha stabildir. Her zaman sınıf adları yerine veri niteliklerini tercih edin.

Sayfalama ile Baş Etme

Birden fazla sayfa kazımak için, istekler arasında makul bir gecikmeyle ofset parametresi üzerinde döngü kurun:

import pandas as pd

all_hotels = []
base_url = "https://www.tripadvisor.com/Hotels-g187147-oa{offset}-Paris_Ile_de_France-Hotels.html"

for page in range(5):  # İlk 5 sayfa
    offset = page * 30
    url = base_url.format(offset=offset) if page > 0 else "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"

    response = session.get(url)
    if response.status_code != 200:
        print(f"{page + 1}. sayfa: {response.status_code} durumu alındı, durduruluyor.")
        break

    soup = BeautifulSoup(response.text, "html.parser")
    cards = soup.select('div[data-test-attribute="location-results-card"]')

    for card in cards:
        title_el = card.select_one('div[data-automation="hotel-card-title"]')
        name = title_el.get_text(strip=True) if title_el else None
        rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
        rating = rating_el.get_text(strip=True) if rating_el else None
        review_el = card.select_one('[data-automation="bubbleReviewCount"]')
        review_count = review_el.get_text(strip=True).replace(",", "").split()[0] if review_el else None

        all_hotels.append({"name": name, "rating": rating, "review_count": review_count})

    print(f"{page + 1}. sayfa: {len(cards)} otel bulundu")
    time.sleep(random.uniform(3, 7))  # Hız limitinden kaçınmak için rastgele gecikme

df = pd.DataFrame(all_hotels)
print(f"\nToplam kazınan otel sayısı: {len(df)}")

time.sleep(random.uniform(3, 7)) önemli. TripAdvisor’ın hız limiti eşiği IP başına kabaca dakikada 10–15 istek civarındadır. Bunun üzerine çıkmak CAPTCHA’ları veya 429 hatalarını tetikler.

Bu Yöntemin Sınırlamaları

Peki bu yöntem ne zaman yetersiz kalır? Requests+BS4 yaklaşımı şu durumlarda başarısız olur:

  • TripAdvisor JavaScript ile render edilen içerik sunuyorsa (bazı arama sonuçları JS gerektirir)
  • Yorum metni "Read more" butonunun arkasında kısaltılmışsa
  • Anti-bot önlemleri JavaScript challenge veya CAPTCHA seviyesine yükselirse
  • Yalnızca istemci tarafında render edildikten sonra görünen veriye ihtiyacınız varsa (fiyatlar, müsaitlik)

Bu senaryolarda Selenium’a (Yöntem 2) veya gizli JSON yöntemine (Yöntem 3) geçmeniz gerekir.

Yöntem 2: Selenium ile TripAdvisor Kazıma (Headless Tarayıcı)

Selenium gerçek bir tarayıcı açar; yani JavaScript’i render edebilir, butonlara tıklayabilir, çerez onay banner’larını yönetebilir ve dinamik içerikle etkileşime girebilir. Bedeli mi? Yaklaşık 5 kat daha yavaş olması ve tarayıcı başına 300–500MB RAM kullanması.

Selenium’u Anti-Detection Ayarlarıyla Yapılandırma

Varsayılan haliyle Selenium kolayca tespit edilir. TripAdvisor’ın fingerprint sistemi bunu anında yakalar. Otomasyon bayraklarını devre dışı bırakmanız gerekir:

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

options = Options()
options.add_argument("--headless=new")  # Yeni headless modu kullan (Chrome 112+)
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--window-size=1920,1080")
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)

driver = webdriver.Chrome(options=options)

# navigator içindeki webdriver özelliğini kaldır
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
})

Bu TripAdvisor için yeterli mi? Küçük ölçekli kazımada (50 sayfanın altında), bu kurulum residential proxy’lerle birlikte genellikle çalışır. Daha büyük hacimlerde undetected-chromedriver veya nodriver gerekebilir — TripAdvisor’ın DataDome koruması, vanilla Selenium’un taklit edemediği TLS fingerprint’ler dahil her istek için 1.000’den fazla sinyali analiz eder.

Selenium ile Otel Arama Sonuçlarını Kazıma

import time
import random

url = "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"
driver.get(url)

# Otel kartlarının yüklenmesini bekle
wait = WebDriverWait(driver, 15)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-test-attribute="location-results-card"]')))

# Çerez onay penceresini işle (varsa)
try:
    cookie_btn = driver.find_element(By.ID, "onetrust-accept-btn-handler")
    cookie_btn.click()
    time.sleep(1)
except:
    pass  # Çerez penceresi yok

# Otel verilerini çıkar
cards = driver.find_elements(By.CSS_SELECTOR, 'div[data-test-attribute="location-results-card"]')

hotels = []
for card in cards:
    try:
        name = card.find_element(By.CSS_SELECTOR, 'div[data-automation="hotel-card-title"]').text
    except:
        name = None
    try:
        rating = card.find_element(By.CSS_SELECTOR, '[data-automation="bubbleRatingValue"]').text
    except:
        rating = None
    try:
        reviews = card.find_element(By.CSS_SELECTOR, '[data-automation="bubbleReviewCount"]').text
    except:
        reviews = None

    hotels.append({"name": name, "rating": rating, "review_count": reviews})

print(f"{len(hotels)} otel kazındı")
for h in hotels[:3]:
    print(h)

Bu sayfa benim makinemde tek bir sayfa için yaklaşık 8 saniye sürdü — requests+BS4 ile 1 saniyenin altına kıyasla. Yüzlerce sayfa kazırken bu 8 kat fark çok hızlı büyür.

"Read More" Butonlarını Açma ve Tam Yorumları Kazıma

Yorum sayfaları uzun yorumları "Read more" butonunun arkasında kısaltır. Selenium bunu tıklayabilir:

review_url = "https://www.tripadvisor.com/Hotel_Review-g187147-d188726-Reviews-Le_Marais_Hotel-Paris_Ile_de_France.html"
driver.get(review_url)

wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-reviewid]')))
time.sleep(2)

# Tüm "Read more" butonlarına tıkla
read_more_buttons = driver.find_elements(By.XPATH, '//button//*[contains(text(), "Read more")]/..')
for btn in read_more_buttons:
    try:
        driver.execute_script("arguments[0].click();", btn)
        time.sleep(0.3)
    except:
        pass

# Yorumları çıkar
review_elements = driver.find_elements(By.CSS_SELECTOR, 'div[data-reviewid]')

reviews = []
for rev in review_elements:
    try:
        title = rev.find_element(By.CSS_SELECTOR, 'div[data-test-target="review-title"]').text
    except:
        title = None
    try:
        body = rev.find_element(By.CSS_SELECTOR, 'q.IRsGHoPm span').text
    except:
        try:
            body = rev.find_element(By.CSS_SELECTOR, 'p.partial_entry').text
        except:
            body = None
    try:
        rating_class = rev.find_element(By.CSS_SELECTOR, 'div[data-test-target="review-rating"] span').get_attribute("class")
        # Yıldız puanı "ui_bubble_rating bubble_50" gibi bir sınıfta kodlanır = 5.0
        rating_num = [c for c in rating_class.split() if "bubble_" in c][0].replace("bubble_", "")
        rating = int(rating_num) / 10
    except:
        rating = None

    reviews.append({"title": title, "body": body, "rating": rating})

print(f"{len(reviews)} yorum kazındı")

Selenium’a Proxy Rotasyonu Eklemek

Sürekli kazıma için proxy rotasyonu gerekir. selenium-wire Ocak 2024’ten beri kullanımdan kalktığı için Chrome’un yerleşik proxy desteğini kullanın:

# Kimlik doğrulama gerektirmeyen proxy ile
proxy = "http://your-proxy-address:port"
options.add_argument(f"--proxy-server={proxy}")

# Kimlik doğrulamalı proxy’ler için Chrome uzantısı veya Selenium 4 BiDi protokolü kullanın

Proxy’leri programatik olarak döndürmek için, her istek grubu için farklı proxy ile yeni bir driver örneği oluşturun. Şık olmayabilir, ama güvenilirdir.

Yöntem 3: Gizli JSON Yöntemi (HTML Ayrıştırmayı Tamamen Atla)

Çoğu rehber bu yöntemi tamamen atlar; bu da yazık — çünkü üç yöntem arasında en hızlı ve en temiz olanı budur. TripAdvisor, yapılandırılmış veriyi HTML sayfalarının içine doğrudan JSON olarak gömer — <script> etiketleri içinde pageManifest ve urqlCache gibi JavaScript değişkenleri olarak. Bu JSON’u çıkarmak size daha temiz veri (sayısal puanlar, ISO formatında tarihler), daha az istek ve JavaScript render ihtiyacı olmadan çalışma avantajı sağlar.

Sayfa Kaynağında Gömülü JSON’u Bulma

Ana fikir şu: Sayfayı almak için basit bir requests.get() kullanabilir, ardından JavaScript’i hiç render etmeden ham HTML’den JSON’u çıkarabilirsiniz.

import requests
import re
import json

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Referer": "https://www.tripadvisor.com/",
    "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
    "Sec-CH-UA-Mobile": "?0",
    "Sec-CH-UA-Platform": '"macOS"',
}

url = "https://www.tripadvisor.com/Hotel_Review-g188590-d194317-Reviews-NH_City_Centre_Amsterdam.html"
response = requests.get(url, headers=headers)

# pageManifest JSON bloğunu çıkar
match = re.search(r"pageManifest:({.+?})};", response.text)
if match:
    page_data = json.loads(match.group(1))
    print("pageManifest verisi bulundu")
    print(f"Anahtarlar: {list(page_data.keys())[:10]}")

Değişken adını nasıl kendin bulursun: Herhangi bir TripAdvisor otel sayfasını Chrome’da aç, sağ tıkla → Sayfa Kaynağını Görüntüle, sonra Ctrl+F ile pageManifest veya urqlCache ya da aggregateRating ara. Veri orada, ayrıştırılmayı bekliyor.

JSON’u Ayrıştırma ve Yapılandırılmış Veriyi Çıkarma

TripAdvisor ayrıca application/ld+json schema.org verisi de gömer; bunu çıkarmak daha da kolaydır:

from parsel import Selector

sel = Selector(text=response.text)

# JSON-LD yapılandırılmış veriyi çıkar
json_ld_scripts = sel.xpath("//script[@type='application/ld+json']/text()").getall()

for script in json_ld_scripts:
    data = json.loads(script)
    if isinstance(data, dict) and data.get("@type") in ["Hotel", "Restaurant", "TouristAttraction"]:
        print(f"Ad: {data.get('name')}")
        print(f"Puan: {data.get('aggregateRating', {}).get('ratingValue')}")
        print(f"Yorum Sayısı: {data.get('aggregateRating', {}).get('reviewCount')}")
        print(f"Fiyat Aralığı: {data.get('priceRange')}")
        print(f"Adres: {data.get('address', {}).get('streetAddress')}")
        print(f"Koordinatlar: {data.get('geo', {}).get('latitude')}, {data.get('geo', {}).get('longitude')}")
        break

JSON-LD verisi statik HTML içine gömülüdür ve JavaScript render etmeyi gerektirmez. İşletme adını, genel puanı, yorum sayısını, adresi, koordinatları, fiyat aralığını ve fotoğraf URL’lerini — tek bir HTML etiketini bile ayrıştırmadan — elde edebilirsiniz.

Daha zengin veri için (tek tek yorumlar, puan dağılımları, olanak listeleri) urqlCache nesnesine ihtiyacınız vardır:

# Detaylı yorum verisi için urqlCache'i çıkar
cache_match = re.search(r'"urqlCache"\s*:\s*({.+?})\s*,\s*"redux"', response.text)
if cache_match:
    cache_data = json.loads(cache_match.group(1))
    # Yorum verisini bulmak için cache içinde dolaş
    for key, value in cache_data.items():
        if "reviews" in str(value).lower()[:100]:
            reviews_data = json.loads(value.get("data", "{}")) if isinstance(value, dict) else None
            if reviews_data:
                print(f"Yorum cache girdisi bulundu: {key[:50]}...")
                break

Tam JSON yolları TripAdvisor ön yüzünü güncellediğinde zaman zaman değişebilir; ancak genel yapı — özet veri için JSON-LD, detaylı veri için urqlCache — yıllardır oldukça stabildir.

TripAdvisor’ın GraphQL API’sini Tersine Mühendislikle Kullanma (İleri Seviye)

Büyük ölçekli çıkarım için TripAdvisor’ın GraphQL uç noktaları yapılandırılmış veriyi doğrudan döndürür. Bu en hızlı yöntemdir, fakat bakım maliyeti en yüksektir.

import httpx
import random
import string

def generate_request_id():
    """X-Requested-By başlık değeri oluştur"""
    random_chars = ''.join(random.choices(string.ascii_letters + string.digits, k=180))
    return f"TNI1625!{random_chars}"

# Paris'te otel arama
search_payload = [{
    "variables": {
        "request": {
            "query": "hotels in Paris",
            "limit": 10,
            "scope": "WORLDWIDE",
            "locale": "en-US",
            "scopeGeoId": 1,
            "searchCenter": None,
            "types": ["LOCATION", "QUERY_SUGGESTION", "RESCUE_RESULT"],
            "locationTypes": ["GEO", "AIRPORT", "ACCOMMODATION", "ATTRACTION", "EATERY", "NEIGHBORHOOD"]
        }
    },
    "extensions": {
        "preRegisteredQueryId": "84b17ed122fbdbd4"
    }
}]

graphql_headers = {
    "Content-Type": "application/json",
    "Accept": "*/*",
    "Accept-Language": "en-US,en;q=0.9",
    "Origin": "https://www.tripadvisor.com",
    "Referer": "https://www.tripadvisor.com/Hotels",
    "X-Requested-By": generate_request_id(),
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
}

with httpx.Client() as client:
    response = client.post(
        "https://www.tripadvisor.com/data/graphql/ids",
        json=search_payload,
        headers=graphql_headers
    )
    if response.status_code == 200:
        results = response.json()
        print(json.dumps(results, indent=2)[:1000])
    else:
        print(f"GraphQL isteği başarısız oldu: {response.status_code}")

Yorumları GraphQL ile çekmek için:

review_payload = [{
    "variables": {
        "locationId": 194317,  # NH City Centre Amsterdam
        "offset": 0,
        "limit": 20,
        "filters": {},
        "sortType": None,
        "sortBy": "date",
        "language": "en",
        "doMachineTranslation": False,
        "photosPerReviewLimit": 3
    },
    "extensions": {
        "preRegisteredQueryId": "ef1a9f94012220d3"
    }
}]

with httpx.Client() as client:
    response = client.post(
        "https://www.tripadvisor.com/data/graphql/ids",
        json=review_payload,
        headers=graphql_headers
    )
    if response.status_code == 200:
        data = response.json()
        reviews = data[0]["data"]["locations"][0]["reviewListPage"]["reviews"]
        total = data[0]["data"]["locations"][0]["reviewListPage"]["totalCount"]
        print(f"Toplam yorum: {total}")
        for r in reviews[:3]:
            print(f"  [{r['rating']}/5] {r['title']} - {r['createdDate']}")

Önemli uyarı: preRegisteredQueryId değerleri (arama için 84b17ed122fbdbd4, yorumlar için ef1a9f94012220d3 gibi) TripAdvisor yeniden dağıtım yaptığında bozulabilir. O zaman istekleriniz sessizce başarısız olur. Sorgu kimliklerini yeniden bulmak için tarayıcı DevTools içindeki ağ isteklerini izlemeniz gerekir.

Bu Yöntem Neden Proxy İhtiyacını Azaltır?

Matematik basit. Requests+BS4 ile 100 otel detay sayfasını kazımak 100 istek gerektirir. Gizli JSON yöntemiyle her istek, tek bir sayfa yüklemesinden ihtiyacınız olan tüm veriyi döndürür — yorum açma veya dinamik içerik yükleme için ek isteğe gerek kalmaz. GraphQL ile tek bir API çağrısı aynı anda 20 yorum döndürebilir. Daha az istek = hız limitine daha az maruz kalma = proxy rotasyonuna daha az ihtiyaç. Küçük ve orta ölçekli projelerde (1.000 sayfanın altında), makul gecikmeler eklerseniz hiç proxy’ye ihtiyaç duymayabilirsiniz.

Tek Bir Yeniden Kullanılabilir Script ile Otel, Restoran ve Turistik Yerleri Kazıyın

Rakip rehberlerin beşte dördü yalnızca otelleri ele alıyor. Oysa TripAdvisor’ın üç ana içerik kategorisi var ve URL kalıpları ile veri alanları kategoriler arasında farklılaşıyor. İşte üçünü de ele alan tek bir fonksiyon nasıl kurulur.

Kategori Başına Mevcut Veri Alanları

AlanOtellerRestoranlarTuristik Yerler
Ad
Puan
Yorum sayısı
Fiyat/Fiyat aralığıBazen
Adres
Mutfak türü
Süre/Tur türü
Olanaklar
Koordinatlar

Yeniden Kullanılabilir scrape_tripadvisor() Fonksiyonu Oluşturma

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random
import re
import json

def scrape_tripadvisor(category, location_id, location_name, num_pages=3):
    """
    TripAdvisor listelemelerini oteller, restoranlar veya turistik yerler için kazır.

    Args:
        category: "hotels", "restaurants" veya "attractions"
        location_id: TripAdvisor geo ID (ör. Paris için "187147")
        location_name: URL dostu isim (ör. "Paris_Ile_de_France")
        num_pages: Kazınacak sayfa sayısı
    """
    url_patterns = {
        "hotels": "https://www.tripadvisor.com/Hotels-g{geo}-oa{offset}-{name}-Hotels.html",
        "restaurants": "https://www.tripadvisor.com/Restaurants-g{geo}-oa{offset}-{name}.html",
        "attractions": "https://www.tripadvisor.com/Attractions-g{geo}-oa{offset}-Activities-{name}.html",
    }

    first_page_patterns = {
        "hotels": "https://www.tripadvisor.com/Hotels-g{geo}-{name}-Hotels.html",
        "restaurants": "https://www.tripadvisor.com/Restaurants-g{geo}-{name}.html",
        "attractions": "https://www.tripadvisor.com/Attractions-g{geo}-Activities-{name}.html",
    }

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Referer": "https://www.tripadvisor.com/",
        "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
        "Sec-CH-UA-Mobile": "?0",
        "Sec-CH-UA-Platform": '"Windows"',
    }

    session = requests.Session()
    session.headers.update(headers)

    all_items = []

    for page in range(num_pages):
        offset = page * 30
        if page == 0:
            url = first_page_patterns[category].format(geo=location_id, name=location_name)
        else:
            url = url_patterns[category].format(geo=location_id, offset=offset, name=location_name)

        response = session.get(url)
        if response.status_code != 200:
            print(f"  {page + 1}. sayfa: {response.status_code} durumu, durduruluyor.")
            break

        soup = BeautifulSoup(response.text, "html.parser")
        cards = soup.select('div[data-test-attribute="location-results-card"]')

        for card in cards:
            item = {"category": category}
            title_el = card.select_one('div[data-automation="hotel-card-title"]') or card.select_one('a[data-automation]')
            item["name"] = title_el.get_text(strip=True) if title_el else None
            rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
            item["rating"] = rating_el.get_text(strip=True) if rating_el else None
            review_el = card.select_one('[data-automation="bubbleReviewCount"]')
            item["review_count"] = review_el.get_text(strip=True) if review_el else None
            all_items.append(item)

        print(f"  {page + 1}. sayfa: {len(cards)} öğe bulundu")
        time.sleep(random.uniform(3, 7))

    return pd.DataFrame(all_items)

# Kullanım örnekleri
print("=== Paris'teki Oteller ===")
hotels_df = scrape_tripadvisor("hotels", "187147", "Paris_Ile_de_France", num_pages=2)
print(hotels_df.head())

print("\n=== Roma'daki Restoranlar ===")
restaurants_df = scrape_tripadvisor("restaurants", "187791", "Rome_Lazio", num_pages=2)
print(restaurants_df.head())

print("\n=== Barselona'daki Turistik Yerler ===")
attractions_df = scrape_tripadvisor("attractions", "187497", "Barcelona_Catalonia", num_pages=2)
print(attractions_df.head())

Tek fonksiyon, üç kategori, sıfır kod tekrarı. TripAdvisor bir seçiciyi değiştirirse, bunu tek bir yerde düzeltirsiniz.

TripAdvisor Sizi Engellediğinde Ne Yapmalısınız? (Anti-Bot Sorun Giderme)

Bu, TripAdvisor kazımaya başladığımda en çok ihtiyaç duyduğum bölümdü ve rakip rehberlerin yapılandırılmış şekilde sunmadığı kısım da bu. TripAdvisor, DataDome’u (günde 5+ trilyon veri noktası analizi) ve Cloudflare WAF’i birlikte kullanıyor. En yaygın hata türleri için bir teşhis tablosu hazırladım:

BelirtiOlası NedenÇözüm
HTTP 403 yanıtıEksik veya şüpheli başlıklar; Cloudflare JS challengeGerçekçi User-Agent, Accept-Language, Referer ve Sec-CH-UA başlıkları kullanın. Başlık tutarlılığını sağlayın.
Veri yerine CAPTCHA sayfasıHız limiti veya tarayıcı fingerprintingResidential proxy kullanın, rastgele gecikmeler ekleyin (istekler arasında 2–7 saniye)
Boş HTML veya boş sayfa gövdesiJavaScript requests ile render edilmediSelenium’a geçin veya sayfa kaynağındaki gizli JSON’dan çıkarın
Kısmi yorumlar / "Read more" açılmıyorİçerik tıklama olayında yükleniyorSelenium ile tıklayın ya da gömülü JSON bloğundan çıkarın
Yorumlar yalnızca tek dildeDil parametresi eksikYorum URL’sine ?filterLang=ALL ekleyin
N sayfasından sonra veri yüklenmiyorOturum bazlı hız limitiOturumları döndürün, partiler arasında çerezleri temizleyin
HTTP 1020 Access DeniedCloudflare IP/ASN engeliVeri merkezi proxy’sinden residential proxy’ye geçin
Challenge döngüsü (sonsuz CAPTCHA)Bozuk çerez kalıcılığıÖnce ana sayfayı ziyaret ederek oturumları ısıtın; cookie jar’ı koruyun

Üstel Geri Çekilme ile Tekrar Deneme Mantığı

Rakip makalelerin hiçbiri bunu gerçekten kodla göstermiyor. İşte yeniden kullanılabilir bir tekrar deneme fonksiyonu:

import time
import random
import requests

def fetch_with_retry(session, url, max_retries=4, base_delay=2, max_delay=60):
    """
    Üstel geri çekilme ve jitter ile URL al.
    Her denemede User-Agent döndürür.
    """
    user_agents = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
    ]

    for attempt in range(max_retries):
        # Her yeniden denemede User-Agent değiştir
        if attempt > 0:
            session.headers["User-Agent"] = random.choice(user_agents)

        try:
            response = session.get(url, timeout=30)

            if response.status_code == 200:
                return response

            if response.status_code == 429:
                # Varsa Retry-After başlığına uy
                retry_after = int(response.headers.get("Retry-After", base_delay * (2 ** attempt)))
                print(f"  Hız sınırına takıldı (429). {retry_after}s bekleniyor...")
                time.sleep(retry_after)
                continue

            if response.status_code in (403, 503):
                wait = min(base_delay * (2 ** attempt) + random.uniform(0, 1), max_delay)
                print(f"  {response.status_code} alındı. {attempt + 1}/{max_retries} denemesi {wait:.1f}s içinde...")
                time.sleep(wait)
                continue

            # Diğer hata kodları — yeniden deneme
            print(f"  {url} için beklenmeyen durum {response.status_code}")
            return response

        except requests.exceptions.Timeout:
            wait = min(base_delay * (2 ** attempt) + random.uniform(0, 1), max_delay)
            print(f"  Zaman aşımı. {attempt + 1}/{max_retries} denemesi {wait:.1f}s içinde...")
            time.sleep(wait)

    print(f"  {url} için {max_retries} denemenin tümü tükendi")
    return None

Başlıkları, Proxy’leri ve Oturumları Döndürme

Sürekli kazıma için, başlık setlerinden oluşan bir havuz tutun ve bunları birlikte döndürün:

import random

HEADER_SETS = [
    {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
        "Sec-CH-UA-Platform": '"Windows"',
    },
    {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
        "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
        "Sec-CH-UA-Platform": '"macOS"',
    },
    {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
        "Sec-CH-UA": '"Google Chrome";v="134", "Not-A.Brand";v="8", "Chromium";v="134"',
        "Sec-CH-UA-Platform": '"Windows"',
    },
]

PROXY_LIST = [
    "http://user:pass@residential-proxy-1:port",
    "http://user:pass@residential-proxy-2:port",
    # Daha fazla residential proxy ekleyin
]

def get_rotated_session():
    """Döndürülmüş başlık ve proxy ile yeni bir oturum oluştur."""
    session = requests.Session()

    # Rastgele bir başlık seti seç
    header_set = random.choice(HEADER_SETS)
    base_headers = {
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
        "Referer": "https://www.tripadvisor.com/",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-CH-UA-Mobile": "?0",
    }
    base_headers.update(header_set)
    session.headers.update(base_headers)

    # Rastgele proxy seç
    if PROXY_LIST:
        proxy = random.choice(PROXY_LIST)
        session.proxies = {"http": proxy, "https": proxy}

    return session

Proxy türü önemlidir. Veri merkezi proxy’leri TripAdvisor tarafından neredeyse anında engellenir (HTTP 1020 Access Denied). Sürekli kazıma için residential proxy’ler zorunludur — tüketici ISP’leri üzerinden yönlendirilirler ve gerçek kullanıcıdan ayırt edilmeleri zordur. Sağlayıcıya göre GB başına 2,50–8,40 dolar ödemeyi bekleyin.

Kazıdığınız TripAdvisor Verisini Dışa Aktarma ve Saklama

Veriyi aldıktan sonra, kullanılabilir bir formata dönüştürmek oldukça kolaydır.

CSV Dışa Aktarma (En Yaygın Yöntem)

import pandas as pd

df = pd.DataFrame(all_hotels)
df.to_csv("tripadvisor_hotels_paris.csv", index=False, encoding="utf-8-sig")
print(f"{len(df)} satır CSV'ye aktarıldı")

encoding='utf-8-sig' önemlidir — CSV’yi Excel’de açtığınızda Latin dışı karakterlerin (Fransızca aksanlar, Çince karakterler vb.) doğru görünmesini sağlar.

JSON Dışa Aktarma (İç İçe Veriler İçin)

Otellerin altında yorumlar gibi iç içe veri varsa, JSON hiyerarşiyi korur:

# Hiyerarşik yapı
hotel_data = {
    "property_id": "d194317",
    "name": "NH City Centre Amsterdam",
    "rating": 4.0,
    "reviews": [
        {"title": "Great location", "rating": 5, "date": "2025-03-15", "text": "..."},
        {"title": "Average stay", "rating": 3, "date": "2025-03-10", "text": "..."},
    ]
}

# Düz analiz için json_normalize kullanın
flat_reviews = pd.json_normalize(
    hotel_data,
    record_path="reviews",
    meta=["property_id", "name"]
)
flat_reviews.to_csv("reviews_flat.csv", index=False)

İlişkisel Veri İçin İki Dosyalı Yaklaşım

Büyük veri kümelerinde iki CSV dosyası kullanırım:

  • hotels.csv — Tesis başına bir satır (düz)
  • reviews.csv — Yorum başına bir satır, property_id yabancı anahtar olarak

Bu yapı, pandas’ta birleştirmeyi, veritabanına yüklemeyi veya BI araçlarına aktarmayı kolaylaştırır.

Tüm bu dışa aktarma mantığıyla uğraşmak istemiyorsanız, Thunderbit ile kazınan veriyi doğrudan Excel, Google Sheets, Airtable veya Notion’a aktarabilirsiniz — hepsi ücretsiz, üstelik kod gerektirmez. Teknik olmayan ekip arkadaşlarınızla sonuç paylaşmanız gerektiğinde çok kullanışlıdır.

Sorumlu ve Verimli TripAdvisor Kazıma İpuçları

Sorumlu kazıma için altı kısa madde:

  • robots.txt dosyasını kontrol edin: TripAdvisor’ın robots.txt dosyası AI eğitim botlarını (GPTBot, ClaudeBot vb.) tamamen engeller. Standart tarayıcılar ise seçici yol kısıtlamalarıyla karşılaşır. tripadvisor.com/robots.txt adresinden inceleyin.
  • Gecikme ekleyin: İstekler arasında 3–7 saniye güvenli bir aralıktır. Dakikada 10–15 isteğin üstüne çıkmak hız sınırlamasını tetikler.
  • Yalnızca herkese açık veriyi kazıyın. Kısıtlı içeriğe erişmek için giriş yapmayın.
  • Veriyi güvenli saklayın ve kişisel bilgi (yorumcu adları vb.) işliyorsanız GDPR/CCPA’ya uyun.
  • Ticari ölçekte veri gerekiyorsa TripAdvisor’ın resmi API’sini değerlendirin. Developer Portal, işletme detayları ile birlikte lokasyon başına en fazla 5 yorum ve 5 fotoğrafa erişim sunar — sınırlı ama yasal ve stabildir.
  • Hukuki bağlamın farkında olun: AB Mahkemesi Ryanair kararı (Aralık 2025), AB genelinde hizmet şartlarına dayalı kazıma yasaklarını güçlendirdi. TripAdvisor’ın Kullanım Şartları açıkça kazımayı yasaklar. Sorumlu şekilde ve kendi riskinizle kazıyın.

Sonuç

Tablonun özeti bu.

  • Requests + BeautifulSoup en basit yoldur. Statik listeleme sayfalarında çalışır, minimum kurulum ister ve hızlıdır. 100 sayfadan az kazıyorsanız ve JavaScript ile render edilen içerik gerekmiyorsa buradan başlayın.
  • Selenium, requests’in yapamadığı her şeyi halleder: dinamik içerik, "Read more" butonları, çerez banner’ları. 5 kat daha yavaştır ve kaynak tüketimi yüksektir; ama sayfayla etkileşim kurmanız gerekiyorsa tek seçenektir.
  • Gizli JSON / GraphQL, en temiz ve en hızlı yaklaşımdır. HTML ayrıştırmadan yapılandırılmış veri sağlar, istek sayısını azaltır (dolayısıyla proxy ihtiyacını da), ve analize hazır formatlarda veri döndürür. Ancak TripAdvisor veri yapısını değiştirdiğinde önceden tersine mühendislik ve ara sıra bakım gerektirir.

Yeniden kullanılabilir scrape_tripadvisor() fonksiyonu otelleri, restoranları ve turistik yerleri kapsar. İkinci bir eğitime ihtiyacınız olmamalı.

Ve eğer rehberin ortasında kod yazmanın size göre olmadığına karar verirseniz — ya da sadece gün sonuna kadar bir tabloda 50 otele ihtiyacınız varsa — Thunderbit’in Chrome uzantısı bunu yapay zekâ destekli alan algılama, otomatik sayfalama ve Excel ya da Google Sheets’e ücretsiz dışa aktarma ile iki tıklamada yapabilir. Python gerekmez.

Daha derine inmek isterseniz, Thunderbit blog ve YouTube kanalımızda daha fazla kazıma anlatımı bulabilirsiniz.

SSS

1. TripAdvisor kazımak yasal mı?

TripAdvisor’ın Kullanım Şartları kazımayı açıkça yasaklar. Ancak mahkemeler genelde, giriş duvarının arkasında olmayan herkese açık verilerin kazınmasının ABD’de Computer Fraud and Abuse Act’i ihlal etmediğine hükmetmiştir. Yine de 2025 AB Mahkemesi Ryanair kararı, Avrupa’da hizmet şartlarına dayalı kısıtlamaları güçlendirdi. Yalnızca herkese açık veriyi kazıyın, robots.txt kurallarına uyun, telifli içeriği yeniden yayımlamayın ve veriyi ticari olarak kullanacaksanız hukuk danışmanına başvurun.

2. TripAdvisor’ı Python olmadan kazıyabilir miyim?

Evet. Thunderbit gibi kod yazmadan kullanılan araçlar, yapay zekâ destekli alan algılama ve otomatik sayfalama ile TripAdvisor’ı doğrudan tarayıcınızdan kazıyabilir. Tarayıcı uzantıları, Google Sheets eklentileri veya ticari kazıma API’leri de kullanabilirsiniz. Python size en fazla kontrolü ve esnekliği verir, ama tek seçenek değildir.

3. TripAdvisor kazırken engellenmemek için ne yapmalıyım?

Temel taktikler: gerçekçi ve tutarlı başlıklar kullanın (özellikle User-Agent ve Sec-CH-UA), residential proxy döndürün (veri merkezi IP’leri hemen engellenir), istekler arasında 3–7 saniyelik rastgele gecikmeler ekleyin, toplam istek sayısını azaltmak için gizli JSON yöntemini kullanın, üstel geri çekilme ile tekrar deneme mantığı uygulayın ve derin sayfalara geçmeden önce ana sayfayı ziyaret ederek oturumları ısıtın.

4. TripAdvisor’dan hangi verileri kazıyabilirim?

Oteller, restoranlar ve turistik yerler — isimler, puanlar, yorum sayıları, fiyat aralıkları, adresler, koordinatlar, olanaklar (oteller), mutfak türleri (restoranlar), tur süreleri (turistik yerler) ve tek tek puanları ve tarihleriyle tam yorum metinleri dahil. Gizli JSON ve GraphQL yaklaşımları, istek başına en zengin veriyi döndürür.

5. Günde TripAdvisor’dan kaç sayfa kazıyabilirim?

Tek bir IP ve makul gecikmelerle: yaklaşık 600–1.000 sayfa/gün. 20 dönen residential proxy ile: istek tabanlı yaklaşımlarda yaklaşık 200.000–300.000 sayfa/gün. Selenium daha yavaştır — proxy başına günde 8.000–12.000 sayfa bekleyin. Gizli JSON/GraphQL yaklaşımı, istek başına en fazla veriyi verdiği için aynı bilgiyi almak adına çok daha az sayfa gerekebilir.

Daha Fazla Öğrenin

Ke
Ke
Thunderbit’ta CTO | Kıdemli Veri Bilimci ve ML Uzmanı Makine öğrenimi ve veri bilimi alanında yaklaşık on yıllık deneyime sahip olan Ke Shen, Columbia University mezunu ve Walmart Labs’te eski Kıdemli Veri Bilimci’dir. Python, R, Java ve İstatistik konularında derin ve meslektaşları tarafından tanınan uzmanlığıyla, karmaşık yapay zekâ algoritmalarını teoriden üretim düzeyinde mimariye taşıma konusunda sahada test edilmiş içgörüler paylaşır.
İçindekiler

Sadece sorarak bir web sayfasını çek

Ne istediğini düz İngilizceyle söyle. Hatta daha iyisi, hiçbir şey söyleme.

Thunderbit’i dene ücretsiz
Yapay Zeka ile Veri Çıkar
Verileri Google Sheets, Airtable veya Notion’a kolayca aktar
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week