Afgelopen week probeerde ik via TripAdvisor de hotelbeoordelingen en het aantal reviews op te halen voor zo’n 200 accommodaties in drie Europese steden. Mijn eerste script — gewoon een simpele requests.get() met standaardheaders — kreeg op elke aanvraag netjes een 403 Forbidden terug. Geen druppel bruikbare data.
TripAdvisor is een van de rijkste openbare databronnen in de reiswereld: meer dan , 8+ miljoen bedrijfsvermeldingen en ongeveer 460 miljoen unieke bezoekers per maand. Het heeft invloed op meer dan aan jaarlijkse reisuitgaven. Maar die data programmatisch ophalen? Daar begint het gedoe. TripAdvisor gebruikt DataDome-botdetectie, Cloudflare WAF, TLS-fingerprinting en JavaScript-challenges — een meerlagige verdedigingsmuur die de meeste ondoordachte scrapingpogingen al stopt voordat ze echt van start gaan. Deze gids is precies de bron die ik zelf had willen hebben: een directe vergelijking van drie Python-aanpakken (plus een no-code optie), complete codevoorbeelden, een gestructureerd anti-bot troubleshooting-gedeelte en herbruikbare patronen die werken voor hotels, restaurants en attracties. Of je nu een Python-beginner bent of een ervaren ontwikkelaar: dit scheelt je een hoop nutteloze 403’s.
Geen code willen schrijven? Scrape TripAdvisor op de makkelijke manier
Ik wil hier meteen eerlijk over zijn. Veel mensen die zoeken op "scrape TripAdvisor met Python" zijn eigenlijk helemaal niet per se van plan om code te schrijven. Ze willen gewoon snel data — hotelnamen, beoordelingen, reviewaantallen, prijzen — in een spreadsheet. Als dat voor jou geldt, is er een veel kortere route.
is een AI-gedreven Chrome-extensie die wij hebben gebouwd. Die kan elke TripAdvisor-pagina lezen en automatisch de juiste kolommen voorstellen om eruit te halen. De workflow is echt twee klikken:
- Open een TripAdvisor-pagina met vermeldingen (bijvoorbeeld zoekresultaten voor "Hotels in Parijs").
- Klik op "AI Suggest Fields" in de Thunderbit-zijbalk. De AI scant de pagina en stelt kolommen voor zoals Hotelnaam, Beoordeling, Aantal reviews, Prijs en Locatie.
- Klik op "Scrape." Thunderbit haalt data uit elke vermelding op de pagina — en handelt paginering automatisch af als je meer resultaten nodig hebt.
- Exporteer naar Excel, Google Sheets, Airtable of Notion. Exporteren is gratis op elk abonnement.
Thunderbit werkt zonder configuratiewijzigingen voor hotels, restaurants en attracties — de AI past zich gewoon aan wat er op de pagina staat. Bij gepagineerde resultaten herkent het automatisch "Next"-knoppen en infinite scroll. En omdat het binnen je echte Chrome-browser draait, gebruikt het je sessiecookies en browserfingerprint, wat het een natuurlijk voordeel geeft tegen botdetectie.
Je kunt het proberen met de — de gratis versie geeft je 6 pagina’s per maand, genoeg om de workflow te testen.
Als je programmatic controle nodig hebt, aangepaste parsingslogica of van plan bent 10.000+ pagina’s te scrapen, dan is Python de juiste route. Lees verder.
Waarom TripAdvisor scrapen met Python?
TripAdvisor-data heeft directe, meetbare impact op de business. Een liet zien dat een stijging van 1 punt op een Global Review Index van 100 punten leidt tot een toename van 0,89% in gemiddelde dagprijs en 1,42% in Revenue Per Available Room. Een apart toonde aan dat een externe stijging van 1 ster in TripAdvisor-beoordeling neerkomt op $55.000–$75.000 extra jaaromzet voor een gemiddeld hotel. Reviews zijn dus niet alleen maar vanity metrics — ze drijven echt omzet.
Zo gebruiken verschillende teams TripAdvisor-data:
| Gebruiksscenario | Wie heeft er baat bij | Benodigde data |
|---|---|---|
| Concurrentieanalyse voor hotels | Hotelketens, revenue managers | Beoordelingen, prijzen, reviewvolume, voorzieningen |
| Marktonderzoek voor restaurants | Restaurantgroepen, foodmerken | Keukentypes, prijsklassen, review-sentiment |
| Trends bij attracties volgen | Reisorganisaties, toerismebureaus | Populariteitsranglijsten, seizoenspatronen |
| Sentimentanalyse | Onderzoekers, data-analisten | Volledige reviewtekst, sterrenbeoordelingen, datums |
| Leadgeneratie | Sales teams, reisbureaus | Bedrijfsnamen, contactgegevens, locaties |
Waarom juist Python? Drie redenen. Ten eerste het ecosysteem: BeautifulSoup, Selenium, Playwright, Scrapy, httpx, pandas — Python heeft meer volwassen scraping- en data-analysetools dan welke andere taal ook. Ten tweede gebruikt Python, wat zorgt voor meer community support, meer StackOverflow-antwoorden en actuelere gidsen. Ten derde het voordeel van de hele pipeline: je kunt scrapen met BeautifulSoup, opschonen met pandas, sentimentanalyse draaien met Hugging Face Transformers en dashboards bouwen — allemaal in één taal. Geen contextswitches.
Drie manieren om TripAdvisor te scrapen met Python (vergeleken)
Elke concurrerende gids kiest één aanpak en gaat daar dan vol op door. Dat helpt niet als je al vóór het coderen wilt beslissen. Hier is de vergelijkingstabel die ik zelf had willen krijgen:
| Aanpak | Snelheid | JS-ondersteuning | Weerstand tegen botdetectie | Complexiteit | Beste voor |
|---|---|---|---|---|---|
requests + BeautifulSoup | ⚡ Snel (~120–200 pagina’s/min ruw) | ❌ Geen | ⚠️ Laag | Makkelijk | Statische lijstpagina’s, kleine projecten |
| Selenium / headless browser | 🐢 Traag (~8–20 pagina’s/min) | ✅ Volledig | ⚠️ Gemiddeld | Gemiddeld | Dynamische content, "Read more"-klikken, cookie-banners |
| Verborgen JSON / GraphQL API | ⚡⚡ Snelst (~200–600 pagina’s/min ruw) | N.v.t. | ✅ Hoger | Moeilijk | Grote aantallen reviews/hoteldata |
| No-code (Thunderbit) | ⚡ Snel | ✅ Ingebouwd | ✅ Ingebouwd | Het makkelijkst | Niet-techneuten, snelle eenmalige exports |
Een paar belangrijke kanttekeningen. Die ruwe snelheden zijn theoretisch — TripAdvisor’s rate limits (~10–15 requests per minuut per IP) begrenzen de echte throughput tot grofweg 10 pagina’s/minuut per IP, ongeacht de aanpak. De verborgen-JSON-methode levert de meeste data per request op, waardoor je minder totale aanvragen doet en dus minder blootstelling hebt aan rate limiting. Selenium is in de praktijk ongeveer 5x trager dan request-gebaseerde methoden, maar is wél de enige optie als je op knoppen moet klikken of JavaScript moet renderen.
De rest van deze gids behandelt alle drie de Python-methoden met volledige code. Kies de aanpak die past bij jouw situatie, of combineer ze (ik gebruik vaak requests+BS4 voor overzichtspagina’s en verborgen JSON voor detailpagina’s).
Je Python-omgeving klaarzetten
Voordat we beginnen, zetten we de omgeving klaar. Je hebt Python 3.10+ nodig (ik raad 3.12 of 3.13 aan — alle grote packages ondersteunen die versies zonder bekende problemen).
Installeer alles in één keer:
1pip install requests beautifulsoup4 selenium httpx parsel pandas curl-cffi
Package-notities:
requests(2.33.1) — HTTP-verzoeken, vereist Python 3.10+beautifulsoup4(4.14.3) — HTML-parsingselenium(4.43.0) — browserautomatisering, vereist Python 3.10+httpx(0.28.1) — async HTTP-clientparsel(1.11.0) — CSS/XPath-selectors (lichter dan BS4)pandas(3.0.2) — data-export, vereist Python 3.11+curl_cffi(0.15.0) — TLS-fingerprint-imitatie (cruciaal om Cloudflare te omzeilen)
ChromeDriver: Als je Selenium gebruikt, goed nieuws: sinds Selenium 4.6+ downloadt Selenium Manager automatisch de juiste ChromeDriver-binary en slaat die op. Handmatige installatie is dus niet nodig. De versieafstemming wordt dynamisch opgelost, dus je hoeft je geen zorgen te maken over mismatches met Chrome.
Virtuele omgeving (aanbevolen):
1python -m venv tripadvisor-scraper
2source tripadvisor-scraper/bin/activate # macOS/Linux
3tripadvisor-scraper\Scripts\activate # Windows
Aanpak 1: TripAdvisor scrapen met Requests en BeautifulSoup
Dit is de simpelste aanpak. Werkt goed voor overzichtspagina’s (hotelzoekresultaten, restaurantlijsten) waar de data die je nodig hebt al in de statische HTML staat. Geen browser, geen JavaScript-rendering, weinig resourcegebruik.
De URL-patronen van TripAdvisor begrijpen
TripAdvisor-URL’s volgen per categorie vrij voorspelbare patronen:
- Hotels:
https://www.tripadvisor.com/Hotels-g{locationId}-{Location_Name}-Hotels.html - Restaurants:
https://www.tripadvisor.com/Restaurants-g{locationId}-{Location_Name}.html - Attracties:
https://www.tripadvisor.com/Attractions-g{locationId}-Activities-{Location_Name}.html
Paginering gebruikt de parameter oa (offset anchors), die in de URL wordt opgenomen. Elke pagina toont 30 resultaten:
- Pagina 1: basis-URL (zonder
oa-parameter) - Pagina 2:
Hotels-g187768-oa30-Italy-Hotels.html - Pagina 3:
Hotels-g187768-oa60-Italy-Hotels.html
Voor reviewpagina’s is de offsetparameter or met stappen van 10:
- Pagina 1:
Reviews-or0-Hotel_Name.html - Pagina 2:
Reviews-or10-Hotel_Name.html
Om reviews in alle talen op te halen, voeg je ?filterLang=ALL toe aan de URL.
Verzoeken sturen met realistische headers
TripAdvisor controleert headers streng. Een request met standaard Python-headers wordt direct geblokkeerd. Je moet een echte Chrome-browser nabootsen:
1import requests
2import time
3import random
4session = requests.Session()
5headers = {
6 "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",
7 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
8 "Accept-Language": "en-US,en;q=0.9",
9 "Accept-Encoding": "gzip, deflate, br",
10 "Referer": "https://www.tripadvisor.com/",
11 "Sec-Fetch-Dest": "document",
12 "Sec-Fetch-Mode": "navigate",
13 "Sec-Fetch-Site": "none",
14 "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
15 "Sec-CH-UA-Mobile": "?0",
16 "Sec-CH-UA-Platform": '"Windows"',
17}
18session.headers.update(headers)
19url = "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"
20response = session.get(url)
21print(f"Status: {response.status_code}")
22print(f"Content length: {len(response.text)} characters")
Belangrijk detail: TripAdvisor controleert of je User-Agent en Sec-CH-UA Client Hints consistent zijn. Als je in de User-Agent zegt dat je Chrome 135 bent, maar je Sec-CH-UA meldt Chrome 120, val je door de mand. Wissel altijd complete header-sets tegelijk, niet losse headers.
Listings parsen met BeautifulSoup
Zodra je een succesvolle response hebt, haal je de data eruit met BeautifulSoup. TripAdvisor gebruikt data-automation- en data-test-attribute-attributen die stabieler zijn dan CSS-classnamen (die regelmatig veranderen):
1from bs4 import BeautifulSoup
2soup = BeautifulSoup(response.text, "html.parser")
3# Alle hotelkaarten vinden
4cards = soup.select('div[data-test-attribute="location-results-card"]')
5hotels = []
6for card in cards:
7 # Hotelnaam
8 title_el = card.select_one('div[data-automation="hotel-card-title"]')
9 name = title_el.get_text(strip=True) if title_el else None
10 # Link naar detailpagina
11 link_el = card.select_one('div[data-automation="hotel-card-title"] a')
12 link = "https://www.tripadvisor.com" + link_el["href"] if link_el else None
13 # Beoordeling
14 rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
15 rating = rating_el.get_text(strip=True) if rating_el else None
16 # Aantal reviews
17 review_el = card.select_one('[data-automation="bubbleReviewCount"]')
18 review_count = review_el.get_text(strip=True).replace(",", "").split()[0] if review_el else None
19 hotels.append({
20 "name": name,
21 "rating": rating,
22 "review_count": review_count,
23 "url": link,
24 })
25print(f"Gevonden: {len(hotels)} hotels op deze pagina")
26for h in hotels[:3]:
27 print(h)
Een opmerking over selectors: TripAdvisor gebruikt geobfusceerde CSS-classnamen (zoals FGwzt, yyzcQ) die bij elke update kunnen veranderen. De data-automation- en data-test-target-attributen zijn veel stabieler. Kies dus altijd voor data-attributen boven classnamen.
Omgaan met paginering
Om meerdere pagina’s te scrapen, loop je met een kleine vertraging door de offsetparameter:
1import pandas as pd
2all_hotels = []
3base_url = "https://www.tripadvisor.com/Hotels-g187147-oa{offset}-Paris_Ile_de_France-Hotels.html"
4for page in range(5): # Eerste 5 pagina's
5 offset = page * 30
6 url = base_url.format(offset=offset) if page > 0 else "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"
7 response = session.get(url)
8 if response.status_code != 200:
9 print(f"Pagina {page + 1}: status {response.status_code}, stoppen.")
10 break
11 soup = BeautifulSoup(response.text, "html.parser")
12 cards = soup.select('div[data-test-attribute="location-results-card"]')
13 for card in cards:
14 title_el = card.select_one('div[data-automation="hotel-card-title"]')
15 name = title_el.get_text(strip=True) if title_el else None
16 rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
17 rating = rating_el.get_text(strip=True) if rating_el else None
18 review_el = card.select_one('[data-automation="bubbleReviewCount"]')
19 review_count = review_el.get_text(strip=True).replace(",", "").split()[0] if review_el else None
20 all_hotels.append({"name": name, "rating": rating, "review_count": review_count})
21 print(f"Pagina {page + 1}: {len(cards)} hotels gevonden")
22 time.sleep(random.uniform(3, 7)) # Willekeurige vertraging om rate limiting te vermijden
23df = pd.DataFrame(all_hotels)
24print(f"\nTotaal gescrapete hotels: {len(df)}")
De time.sleep(random.uniform(3, 7)) is belangrijk. TripAdvisor’s drempel voor rate limiting ligt grofweg op 10–15 requests per minuut per IP. Sneller gaan triggert CAPTCHAs of 429-fouten.
Beperkingen van deze aanpak
Waar loopt dit vast? De requests+BS4-aanpak faalt wanneer:
- TripAdvisor content via JavaScript rendert (sommige zoekresultaatpagina’s vereisen JS)
- Reviewteksten achter "Read more"-knoppen zijn afgekapt
- Anti-botmaatregelen escaleren naar JavaScript-challenges of CAPTCHAs
- Je data nodig hebt die pas na client-side rendering verschijnt (prijzen, beschikbaarheid)
Voor deze scenario’s heb je Selenium nodig (Aanpak 2) of de verborgen JSON-methode (Aanpak 3).
Aanpak 2: TripAdvisor scrapen met Selenium (headless browser)
Selenium start een echte browser, waardoor JavaScript gerenderd kan worden, knoppen geklikt kunnen worden, cookie-consentbanners verwerkt kunnen worden en dynamische content interactief is. De prijs: ongeveer en 300–500 MB RAM per browserinstantie.
Selenium instellen met anti-detectie-opties
Uit de doos is Selenium vrij makkelijk te detecteren. TripAdvisor’s fingerprinting pakt het direct op. Je moet automation-flags uitschakelen:
1from selenium import webdriver
2from selenium.webdriver.chrome.options import Options
3from selenium.webdriver.common.by import By
4from selenium.webdriver.support.ui import WebDriverWait
5from selenium.webdriver.support import expected_conditions as EC
6options = Options()
7options.add_argument("--headless=new") # Nieuwe headless-modus gebruiken (Chrome 112+)
8options.add_argument("--disable-blink-features=AutomationControlled")
9options.add_argument("--window-size=1920,1080")
10options.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")
11options.add_experimental_option("excludeSwitches", ["enable-automation"])
12options.add_experimental_option("useAutomationExtension", False)
13driver = webdriver.Chrome(options=options)
14# webdriver-property uit navigator verwijderen
15driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
16 "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
17})
Is dit genoeg voor TripAdvisor? Voor kleinschalig scrapen (onder 50 pagina’s) werkt deze setup meestal prima in combinatie met residential proxies. Voor grotere volumes heb je mogelijk undetected-chromedriver of nodriver nodig — TripAdvisor’s DataDome-bescherming analyseert meer dan 1.000 signalen per request, inclusief TLS-fingerprints die gewone Selenium niet goed kan nabootsen.
Hotelzoekresultaten scrapen met Selenium
1import time
2import random
3url = "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"
4driver.get(url)
5# Wachten tot hotelkaarten geladen zijn
6wait = WebDriverWait(driver, 15)
7wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-test-attribute="location-results-card"]')))
8# Cookie-consentpopup afhandelen (als die verschijnt)
9try:
10 cookie_btn = driver.find_element(By.ID, "onetrust-accept-btn-handler")
11 cookie_btn.click()
12 time.sleep(1)
13except:
14 pass # Geen cookiepopup
15# Hoteldata extraheren
16cards = driver.find_elements(By.CSS_SELECTOR, 'div[data-test-attribute="location-results-card"]')
17hotels = []
18for card in cards:
19 try:
20 name = card.find_element(By.CSS_SELECTOR, 'div[data-automation="hotel-card-title"]').text
21 except:
22 name = None
23 try:
24 rating = card.find_element(By.CSS_SELECTOR, '[data-automation="bubbleRatingValue"]').text
25 except:
26 rating = None
27 try:
28 reviews = card.find_element(By.CSS_SELECTOR, '[data-automation="bubbleReviewCount"]').text
29 except:
30 reviews = None
31 hotels.append({"name": name, "rating": rating, "review_count": reviews})
32print(f"Gescrapet: {len(hotels)} hotels")
33for h in hotels[:3]:
34 print(h)
Dit duurde op mijn machine ongeveer 8 seconden voor één pagina — vergeleken met minder dan 1 seconde met requests+BS4. Dat verschil van 8x telt snel op als je honderden pagina’s scrapt.
"Read more" uitklappen en volledige reviews scrapen
Reviewpagina’s kappen lange reviews af achter een "Read more"-knop. Selenium kan daarop klikken:
1review_url = "https://www.tripadvisor.com/Hotel_Review-g187147-d188726-Reviews-Le_Marais_Hotel-Paris_Ile_de_France.html"
2driver.get(review_url)
3wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-reviewid]')))
4time.sleep(2)
5# Alle "Read more"-knoppen aanklikken
6read_more_buttons = driver.find_elements(By.XPATH, '//button//*[contains(text(), "Read more")]/..')
7for btn in read_more_buttons:
8 try:
9 driver.execute_script("arguments[0].click();", btn)
10 time.sleep(0.3)
11 except:
12 pass
13# Reviews extraheren
14review_elements = driver.find_elements(By.CSS_SELECTOR, 'div[data-reviewid]')
15reviews = []
16for rev in review_elements:
17 try:
18 title = rev.find_element(By.CSS_SELECTOR, 'div[data-test-target="review-title"]').text
19 except:
20 title = None
21 try:
22 body = rev.find_element(By.CSS_SELECTOR, 'q.IRsGHoPm span').text
23 except:
24 try:
25 body = rev.find_element(By.CSS_SELECTOR, 'p.partial_entry').text
26 except:
27 body = None
28 try:
29 rating_class = rev.find_element(By.CSS_SELECTOR, 'div[data-test-target="review-rating"] span').get_attribute("class")
30 # Rating gecodeerd in class zoals "ui_bubble_rating bubble_50" = 5.0
31 rating_num = [c for c in rating_class.split() if "bubble_" in c][0].replace("bubble_", "")
32 rating = int(rating_num) / 10
33 except:
34 rating = None
35 reviews.append({"title": title, "body": body, "rating": rating})
36print(f"Gescrapet: {len(reviews)} reviews")
Proxy-rotatie toevoegen aan Selenium
Voor langdurig scrapen heb je proxyrotatie nodig. Omdat selenium-wire sinds januari 2024 is gedepricieerd, gebruik je Chrome’s ingebouwde proxysteun:
1# Zonder authenticatie op de proxy
2proxy = "http://your-proxy-address:port"
3options.add_argument(f"--proxy-server={proxy}")
4# Voor proxies met authenticatie gebruik je een Chrome-extensie of Selenium 4's BiDi-protocol
Voor programmatic rotatie maak je per batch verzoeken een nieuwe driverinstantie met een andere proxy aan. Niet elegant, maar wel betrouwbaar.
Aanpak 3: De verborgen JSON-methode (HTML-parsing volledig overslaan)
De meeste gidsen slaan deze aanpak over, en dat is zonde — dit is namelijk de snelste en schoonste van de drie. TripAdvisor stopt gestructureerde data rechtstreeks als JSON in de HTML-pagina’s — in <script>-tags als JavaScript-variabelen zoals pageManifest en urqlCache. Door deze JSON uit te lezen krijg je schonere data (ratings als getallen, datums in ISO-formaat), minder requests en hoef je geen JavaScript te renderen.
De ingesloten JSON vinden in de broncode van de pagina
De kern: je kunt gewoon een simpele requests.get() gebruiken om de pagina op te halen en daarna de JSON uit de ruwe HTML halen, zonder ooit JavaScript te renderen.
1import requests
2import re
3import json
4headers = {
5 "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",
6 "Accept-Language": "en-US,en;q=0.9",
7 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
8 "Referer": "https://www.tripadvisor.com/",
9 "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
10 "Sec-CH-UA-Mobile": "?0",
11 "Sec-CH-UA-Platform": '"macOS"',
12}
13url = "https://www.tripadvisor.com/Hotel_Review-g188590-d194317-Reviews-NH_City_Centre_Amsterdam.html"
14response = requests.get(url, headers=headers)
15# De pageManifest-JSON-blok eruit halen
16match = re.search(r"pageManifest:({.+?})};", response.text)
17if match:
18 page_data = json.loads(match.group(1))
19 print("pageManifest-data gevonden")
20 print(f"Keys: {list(page_data.keys())[:10]}")
Hoe je zelf de variabelenaam vindt: Open een willekeurige TripAdvisor-hotelpagina in Chrome, klik rechts → Paginabron bekijken, en zoek met Ctrl+F op pageManifest of urqlCache of aggregateRating. De data staat er gewoon, klaar om geparsed te worden.
De JSON parsen en gestructureerde data extraheren
TripAdvisor stopt ook application/ld+json schema.org-data in de pagina, en die is nog makkelijker te lezen:
1from parsel import Selector
2sel = Selector(text=response.text)
3# JSON-LD gestructureerde data extraheren
4json_ld_scripts = sel.xpath("//script[@type='application/ld+json']/text()").getall()
5for script in json_ld_scripts:
6 data = json.loads(script)
7 if isinstance(data, dict) and data.get("@type") in ["Hotel", "Restaurant", "TouristAttraction"]:
8 print(f"Naam: {data.get('name')}")
9 print(f"Beoordeling: {data.get('aggregateRating', {}).get('ratingValue')}")
10 print(f"Aantal reviews: {data.get('aggregateRating', {}).get('reviewCount')}")
11 print(f"Prijsklasse: {data.get('priceRange')}")
12 print(f"Adres: {data.get('address', {}).get('streetAddress')}")
13 print(f"Coördinaten: {data.get('geo', {}).get('latitude')}, {data.get('geo', {}).get('longitude')}")
14 break
De JSON-LD-data zit in statische HTML en vereist GEEN JavaScript-rendering. Je krijgt de naam van de locatie, de totale beoordeling, het aantal reviews, adres, coördinaten, prijsklasse en foto-URL’s — allemaal zonder ook maar één HTML-tag te hoeven parsen.
Voor uitgebreidere data (individuele reviews, beoordelingsverdelingen, voorzieningenlijsten) heb je het urqlCache-object nodig:
1# urqlCache extraheren voor gedetailleerde reviewdata
2cache_match = re.search(r'"urqlCache"\s*:\s*({.+?})\s*,\s*"redux"', response.text)
3if cache_match:
4 cache_data = json.loads(cache_match.group(1))
5 # Door de cache navigeren om reviewdata te vinden
6 for key, value in cache_data.items():
7 if "reviews" in str(value).lower()[:100]:
8 reviews_data = json.loads(value.get("data", "{}")) if isinstance(value, dict) else None
9 if reviews_data:
10 print(f"Review-cache-entry gevonden: {key[:50]}...")
11 break
De exacte JSON-paden veranderen af en toe wanneer TripAdvisor zijn frontend bijwerkt, maar de algemene structuur — JSON-LD voor samenvattende data, urqlCache voor detaildata — is al jaren redelijk stabiel.
TripAdvisor’s GraphQL API reverse-engineeren (gevorderd)
Voor grootschalige extractie leveren TripAdvisor’s GraphQL-endpoints direct gestructureerde data terug. Dit is de snelste methode, maar vraagt ook het meeste onderhoud.
1import httpx
2import random
3import string
4def generate_request_id():
5 """Genereer de waarde voor de X-Requested-By header"""
6 random_chars = ''.join(random.choices(string.ascii_letters + string.digits, k=180))
7 return f"TNI1625!{random_chars}"
8# Zoek hotels in Parijs
9search_payload = [{
10 "variables": {
11 "request": {
12 "query": "hotels in Paris",
13 "limit": 10,
14 "scope": "WORLDWIDE",
15 "locale": "en-US",
16 "scopeGeoId": 1,
17 "searchCenter": None,
18 "types": ["LOCATION", "QUERY_SUGGESTION", "RESCUE_RESULT"],
19 "locationTypes": ["GEO", "AIRPORT", "ACCOMMODATION", "ATTRACTION", "EATERY", "NEIGHBORHOOD"]
20 }
21 },
22 "extensions": {
23 "preRegisteredQueryId": "84b17ed122fbdbd4"
24 }
25}]
26graphql_headers = {
27 "Content-Type": "application/json",
28 "Accept": "*/*",
29 "Accept-Language": "en-US,en;q=0.9",
30 "Origin": "https://www.tripadvisor.com",
31 "Referer": "https://www.tripadvisor.com/Hotels",
32 "X-Requested-By": generate_request_id(),
33 "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",
34}
35with httpx.Client() as client:
36 response = client.post(
37 "https://www.tripadvisor.com/data/graphql/ids",
38 json=search_payload,
39 headers=graphql_headers
40 )
41 if response.status_code == 200:
42 results = response.json()
43 print(json.dumps(results, indent=2)[:1000])
44 else:
45 print(f"GraphQL-aanvraag mislukt: {response.status_code}")
Voor het ophalen van reviews via GraphQL:
1review_payload = [{
2 "variables": {
3 "locationId": 194317, # NH City Centre Amsterdam
4 "offset": 0,
5 "limit": 20,
6 "filters": {},
7 "sortType": None,
8 "sortBy": "date",
9 "language": "en",
10 "doMachineTranslation": False,
11 "photosPerReviewLimit": 3
12 },
13 "extensions": {
14 "preRegisteredQueryId": "ef1a9f94012220d3"
15 }
16}]
17with httpx.Client() as client:
18 response = client.post(
19 "https://www.tripadvisor.com/data/graphql/ids",
20 json=review_payload,
21 headers=graphql_headers
22 )
23 if response.status_code == 200:
24 data = response.json()
25 reviews = data[0]["data"]["locations"][0]["reviewListPage"]["reviews"]
26 total = data[0]["data"]["locations"][0]["reviewListPage"]["totalCount"]
27 print(f"Totaal reviews: {total}")
28 for r in reviews[:3]:
29 print(f" [{r['rating']}/5] {r['title']} - {r['createdDate']}")
Belangrijke kanttekening: De preRegisteredQueryId-waarden (zoals 84b17ed122fbdbd4 voor zoeken en ef1a9f94012220d3 voor reviews) kunnen breken wanneer TripAdvisor opnieuw uitrolt. Als dat gebeurt, falen je requests stilletjes. Dan moet je de query-IDs opnieuw achterhalen via netwerkverkeer in de DevTools van de browser.
Waarom deze methode minder proxies nodig heeft
De rekensom is simpel. Met requests+BS4 heb je voor 100 hoteldetailpagina’s ook 100 requests nodig. Met de verborgen JSON-methode levert elke request alle data van één pagina in één keer op — geen extra requests voor het uitklappen van reviews of het laden van dynamische content. Met GraphQL kan één API-call meteen 20 reviews teruggeven. Minder requests = minder blootstelling aan rate limiting = minder noodzaak voor proxyrotatie. Voor kleine tot middelgrote projecten (onder 1.000 pagina’s) heb je misschien zelfs helemaal geen proxies nodig als je nette vertragingen inbouwt.
Hotels, restaurants en attracties scrapen met één herbruikbaar script
Vier van de vijf concurrerende gidsen behandelen alleen hotels. Maar TripAdvisor heeft drie kerncategorieën, en de URL-patronen en datavelden verschillen per categorie. Zo bouw je één functie die ze allemaal aankan.
Beschikbare datavelden per categorie
| Veld | Hotels | Restaurants | Attracties |
|---|---|---|---|
| Naam | ✅ | ✅ | ✅ |
| Beoordeling | ✅ | ✅ | ✅ |
| Aantal reviews | ✅ | ✅ | ✅ |
| Prijs/Prijsklasse | ✅ | ✅ | Soms |
| Adres | ✅ | ✅ | ✅ |
| Keukentype | ❌ | ✅ | ❌ |
| Duur/Type tour | ❌ | ❌ | ✅ |
| Voorzieningen | ✅ | ❌ | ❌ |
| Coördinaten | ✅ | ✅ | ✅ |
Een herbruikbare scrape_tripadvisor()-functie bouwen
1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4import time
5import random
6import re
7import json
8def scrape_tripadvisor(category, location_id, location_name, num_pages=3):
9 """
10 Scrape TripAdvisor-vermeldingen voor hotels, restaurants of attracties.
11 Args:
12 category: "hotels", "restaurants" of "attractions"
13 location_id: TripAdvisor geo-ID (bijv. "187147" voor Parijs)
14 location_name: URL-vriendelijke naam (bijv. "Paris_Ile_de_France")
15 num_pages: Aantal pagina's om te scrapen
16 """
17 url_patterns = {
18 "hotels": "https://www.tripadvisor.com/Hotels-g{geo}-oa{offset}-{name}-Hotels.html",
19 "restaurants": "https://www.tripadvisor.com/Restaurants-g{geo}-oa{offset}-{name}.html",
20 "attractions": "https://www.tripadvisor.com/Attractions-g{geo}-oa{offset}-Activities-{name}.html",
21 }
22 first_page_patterns = {
23 "hotels": "https://www.tripadvisor.com/Hotels-g{geo}-{name}-Hotels.html",
24 "restaurants": "https://www.tripadvisor.com/Restaurants-g{geo}-{name}.html",
25 "attractions": "https://www.tripadvisor.com/Attractions-g{geo}-Activities-{name}.html",
26 }
27 headers = {
28 "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",
29 "Accept-Language": "en-US,en;q=0.9",
30 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
31 "Referer": "https://www.tripadvisor.com/",
32 "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
33 "Sec-CH-UA-Mobile": "?0",
34 "Sec-CH-UA-Platform": '"Windows"',
35 }
36 session = requests.Session()
37 session.headers.update(headers)
38 all_items = []
39 for page in range(num_pages):
40 offset = page * 30
41 if page == 0:
42 url = first_page_patterns[category].format(geo=location_id, name=location_name)
43 else:
44 url = url_patterns[category].format(geo=location_id, offset=offset, name=location_name)
45 response = session.get(url)
46 if response.status_code != 200:
47 print(f" Pagina {page + 1}: status {response.status_code}, stoppen.")
48 break
49 soup = BeautifulSoup(response.text, "html.parser")
50 cards = soup.select('div[data-test-attribute="location-results-card"]')
51 for card in cards:
52 item = {"category": category}
53 title_el = card.select_one('div[data-automation="hotel-card-title"]') or card.select_one('a[data-automation]')
54 item["name"] = title_el.get_text(strip=True) if title_el else None
55 rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
56 item["rating"] = rating_el.get_text(strip=True) if rating_el else None
57 review_el = card.select_one('[data-automation="bubbleReviewCount"]')
58 item["review_count"] = review_el.get_text(strip=True) if review_el else None
59 all_items.append(item)
60 print(f" Pagina {page + 1}: {len(cards)} items gevonden")
61 time.sleep(random.uniform(3, 7))
62 return pd.DataFrame(all_items)
63# Voorbeelden van gebruik
64print("=== Hotels in Parijs ===")
65hotels_df = scrape_tripadvisor("hotels", "187147", "Paris_Ile_de_France", num_pages=2)
66print(hotels_df.head())
67print("\n=== Restaurants in Rome ===")
68restaurants_df = scrape_tripadvisor("restaurants", "187791", "Rome_Lazio", num_pages=2)
69print(restaurants_df.head())
70print("\n=== Attracties in Barcelona ===")
71attractions_df = scrape_tripadvisor("attractions", "187497", "Barcelona_Catalonia", num_pages=2)
72print(attractions_df.head())
Eén functie, drie categorieën, geen code-duplicatie. Als TripAdvisor een selector wijzigt, los je het op één plek op.
Wat te doen als TripAdvisor je blokkeert (anti-bot troubleshooting)
Dit is het gedeelte dat ik het hardst nodig had toen ik begon met TripAdvisor scrapen, en precies het stukje dat geen enkele concurrerende gids netjes gestructureerd aanbiedt. TripAdvisor gebruikt samen DataDome (dat per dag analyseert) en Cloudflare WAF. Hieronder staat een diagnosetabel voor de meest voorkomende foutscenario’s:
| Symptoom | Waarschijnlijke oorzaak | Oplossing |
|---|---|---|
| HTTP 403-response | Ontbrekende of verdachte headers; Cloudflare JS-challenge | Stel realistische User-Agent, Accept-Language, Referer en Sec-CH-UA-headers in. Zorg dat de headers onderling consistent zijn. |
| CAPTCHA-pagina in plaats van data | Rate limiting of browserfingerprinting | Roteer residential proxies, voeg willekeurige vertragingen toe (2–7 seconden tussen requests) |
| Lege HTML of lege paginabody | JavaScript niet gerenderd door requests | Schakel over op Selenium of haal data uit de verborgen JSON in de broncode |
| Gedeeltelijke reviews / "Read more" klapt niet uit | Content wordt geladen via een klik-event | Gebruik Selenium .click() of haal data uit het ingesloten JSON-blok |
| Reviews slechts in één taal | Ontbrekende taalparameter | Voeg ?filterLang=ALL toe aan de review-URL |
| Data stopt na N pagina’s | Sessiegebaseerde rate limit | Wissel sessies af, wis cookies tussen batches |
| HTTP 1020 Access Denied | IP/ASN geblokkeerd door Cloudflare | Stap over van datacenter- naar residential proxies |
| Challenge loop (oneindige CAPTCHA) | Cookie-persistentie stuk | Laat sessies opwarmen door eerst de homepage te bezoeken; behoud de cookie jar |
Retry-logica met exponential backoff
Geen enkel concurrerend artikel laat deze code echt zien. Hier is een herbruikbare retry-functie:
1import time
2import random
3import requests
4def fetch_with_retry(session, url, max_retries=4, base_delay=2, max_delay=60):
5 """
6 Haal een URL op met exponential backoff en jitter.
7 Wisselt de User-Agent bij elke retry.
8 """
9 user_agents = [
10 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
11 "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",
12 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
13 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
14 ]
15 for attempt in range(max_retries):
16 # User-Agent roteren bij een retry
17 if attempt > 0:
18 session.headers["User-Agent"] = random.choice(user_agents)
19 try:
20 response = session.get(url, timeout=30)
21 if response.status_code == 200:
22 return response
23 if response.status_code == 429:
24 # Respecteer Retry-After-header als die er is
25 retry_after = int(response.headers.get("Retry-After", base_delay * (2 ** attempt)))
26 print(f" Rate limited (429). Wachten {retry_after}s...")
27 time.sleep(retry_after)
28 continue
29 if response.status_code in (403, 503):
30 wait = min(base_delay * (2 ** attempt) + random.uniform(0, 1), max_delay)
31 print(f" Kreeg {response.status_code}. Retry {attempt + 1}/{max_retries} over {wait:.1f}s...")
32 time.sleep(wait)
33 continue
34 # Andere foutcodes — niet opnieuw proberen
35 print(f" Onverwachte status {response.status_code} voor {url}")
36 return response
37 except requests.exceptions.Timeout:
38 wait = min(base_delay * (2 ** attempt) + random.uniform(0, 1), max_delay)
39 print(f" Timeout. Retry {attempt + 1}/{max_retries} over {wait:.1f}s...")
40 time.sleep(wait)
41 print(f" Alle {max_retries} retries opgebruikt voor {url}")
42 return None
Headers, proxies en sessies roteren
Voor langdurig scrapen houd je een pool van header-sets aan en roteer je die samen:
1import random
2HEADER_SETS = [
3 {
4 "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",
5 "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
6 "Sec-CH-UA-Platform": '"Windows"',
7 },
8 {
9 "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",
10 "Sec-CH-UA": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
11 "Sec-CH-UA-Platform": '"macOS"',
12 },
13 {
14 "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",
15 "Sec-CH-UA": '"Google Chrome";v="134", "Not-A.Brand";v="8", "Chromium";v="134"',
16 "Sec-CH-UA-Platform": '"Windows"',
17 },
18]
19PROXY_LIST = [
20 "http://user:pass@residential-proxy-1:port",
21 "http://user:pass@residential-proxy-2:port",
22 # Voeg meer residential proxies toe
23]
24def get_rotated_session():
25 """Maak een nieuwe sessie met geroteerde headers en proxy."""
26 session = requests.Session()
27 # Kies een willekeurige header-set
28 header_set = random.choice(HEADER_SETS)
29 base_headers = {
30 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
31 "Accept-Language": "en-US,en;q=0.9",
32 "Accept-Encoding": "gzip, deflate, br",
33 "Referer": "https://www.tripadvisor.com/",
34 "Sec-Fetch-Dest": "document",
35 "Sec-Fetch-Mode": "navigate",
36 "Sec-CH-UA-Mobile": "?0",
37 }
38 base_headers.update(header_set)
39 session.headers.update(base_headers)
40 # Kies een willekeurige proxy
41 if PROXY_LIST:
42 proxy = random.choice(PROXY_LIST)
43 session.proxies = {"http": proxy, "https": proxy}
44 return session
Het type proxy is belangrijk. Datacenter-proxies worden door TripAdvisor vrijwel meteen geblokkeerd (HTTP 1020 Access Denied). Residential proxies zijn essentieel voor langdurig scrapen — ze lopen via consumenten-ISP’s en zijn niet van echte gebruikers te onderscheiden. Reken op $2,50–$8,40/GB, afhankelijk van de provider.
Je gescrapete TripAdvisor-data exporteren en opslaan
Zodra je de data hebt, is het vrij eenvoudig om die in een bruikbaar formaat te krijgen.
CSV-export (meest gebruikt)
1import pandas as pd
2df = pd.DataFrame(all_hotels)
3df.to_csv("tripadvisor_hotels_paris.csv", index=False, encoding="utf-8-sig")
4print(f"{len(df)} rijen geëxporteerd naar CSV")
De encoding='utf-8-sig' is belangrijk — daarmee toont Excel niet-Latijnse tekens correct (Franse accenten, Chinese karakters, enz.) wanneer het de CSV opent.
JSON-export (voor geneste data)
Als je reviews onder hotels hebt genest, behoudt JSON de hiërarchie:
1# Hiërarchische structuur
2hotel_data = {
3 "property_id": "d194317",
4 "name": "NH City Centre Amsterdam",
5 "rating": 4.0,
6 "reviews": [
7 {"title": "Geweldige locatie", "rating": 5, "date": "2025-03-15", "text": "..."},
8 {"title": "Gemiddeld verblijf", "rating": 3, "date": "2025-03-10", "text": "..."},
9 ]
10}
11# Voor vlakke analyse gebruik je json_normalize
12flat_reviews = pd.json_normalize(
13 hotel_data,
14 record_path="reviews",
15 meta=["property_id", "name"]
16)
17flat_reviews.to_csv("reviews_flat.csv", index=False)
Twee-bestanden-aanpak voor relationele data
Voor grote datasets gebruik ik meestal twee CSV-bestanden:
hotels.csv— één rij per accommodatie (vlak)reviews.csv— één rij per review, metproperty_idals foreign key
Dat maakt het makkelijk om te joinen in pandas, in een database te laden of te importeren in BI-tools.
Als je niet met al die exportlogica wilt rommelen, laat Thunderbit je naar Excel, Google Sheets, Airtable of Notion — allemaal gratis, allemaal zonder code. Handig als je resultaten wilt delen met niet-technische collega’s.
Tips voor verantwoord en efficiënt TripAdvisor-scrapen
Verantwoord scrapen in zes punten:
- Controleer
robots.txt: TripAdvisor’s robots.txt blokkeert AI-trainingsbots (GPTBot, ClaudeBot, enz.) volledig. Standaard crawlers krijgen selectieve padbeperkingen. Bekijk het optripadvisor.com/robots.txt. - Voeg vertragingen toe: 3–7 seconden tussen requests is een veilige bandbreedte. Sneller dan 10–15 requests per minuut per IP leidt tot rate limiting.
- Scrape alleen openbare data. Log niet in om afgeschermde content te bereiken.
- Bewaar data veilig en houd rekening met GDPR/AVG als je persoonsgegevens verwerkt (zoals namen van reviewers).
- Overweeg TripAdvisor’s officiële API als je data nodig hebt op commerciële schaal. Het biedt toegang tot bedrijfsgegevens plus maximaal 5 reviews en 5 foto’s per locatie — beperkt, maar legaal en stabiel.
- Wees je bewust van de juridische context: De heeft ToS-gebaseerde scrapingverboden binnen de EU verder aangescherpt. TripAdvisor’s Terms of Service verbieden scraping expliciet. Scrape verantwoord en op eigen risico.
Afronding
Dit is het complete plaatje.
- Requests + BeautifulSoup is de simpelste route. Het werkt voor statische overzichtspagina’s, vereist minimale setup en is snel. Begin hier als je minder dan 100 pagina’s scrapt en geen JavaScript-gerenderde content nodig hebt.
- Selenium doet alles wat requests niet kan: dynamische content, "Read more"-knoppen, cookie-banners. Het is 5x trager en zwaarder qua resources, maar de enige optie als je met de pagina moet interacteren.
- Verborgen JSON / GraphQL is de schoonste en snelste aanpak. Je krijgt gestructureerde data zonder HTML te parsen, je doet minder requests (en hebt daardoor minder proxies nodig) en de output is direct analyse-klaar. Wel vraagt het meer reverse engineering vooraf en af en toe onderhoud wanneer TripAdvisor zijn datastructuur wijzigt.
De herbruikbare scrape_tripadvisor()-functie dekt hotels, restaurants en attracties af. Je zou hier eigenlijk geen tweede tutorial meer voor nodig moeten hebben.
En als je halverwege besluit dat coderen toch niets voor jou is — of je gewoon vóór het einde van de dag 50 hotels in een spreadsheet nodig hebt — dan kan de dat in twee klikken doen met AI-gestuurde veldherkenning, automatische paginering en gratis export naar Excel of Google Sheets. Geen Python nodig.
Als je dieper wilt gaan, hebben we meer scraping-uitleg op de en ons .
Veelgestelde vragen
1. Is het legaal om TripAdvisor te scrapen?
TripAdvisor’s Terms of Service verbieden scraping expliciet. Rechtbanken hebben echter in het algemeen geoordeeld dat het scrapen van publiek beschikbare data — dus niet achter een login — in de VS niet in strijd is met de Computer Fraud and Abuse Act. Dat gezegd hebbende: de EU Court Ryanair-uitspraak van 2025 heeft ToS-gebaseerde beperkingen in Europa aangescherpt. Scrape alleen openbare data, respecteer robots.txt, herpubliceer geen auteursrechtelijk beschermde content en vraag juridisch advies als je de data commercieel gebruikt.
2. Kan ik TripAdvisor scrapen zonder Python?
Ja. No-code tools zoals kunnen TripAdvisor direct vanuit je browser scrapen met AI-veldherkenning en automatische paginering. Je kunt ook browserextensies, Google Sheets-add-ons of commerciële scraping-API’s gebruiken. Python geeft je de meeste controle en flexibiliteit, maar het is zeker niet de enige optie.
3. Hoe voorkom ik dat ik geblokkeerd word bij het scrapen van TripAdvisor?
De belangrijkste tactieken: gebruik realistische en consistente headers (vooral User-Agent en Sec-CH-UA), roteer residential proxies (datacenter-IP’s worden vrijwel meteen geblokkeerd), voeg willekeurige vertragingen van 3–7 seconden toe tussen requests, gebruik de verborgen JSON-methode om het aantal requests te minimaliseren, implementeer retry-logica met exponential backoff, en warm sessies op door eerst de homepage te bezoeken voordat je diepe pagina’s opvraagt.
4. Welke data kan ik van TripAdvisor scrapen?
Hotels, restaurants en attracties — inclusief namen, beoordelingen, reviewaantallen, prijsklassen, adressen, coördinaten, voorzieningen (hotels), keukentypes (restaurants), tourduur (attracties) en volledige reviewtekst met individuele ratings en datums. De verborgen JSON- en GraphQL-aanpakken leveren per request de rijkste data.
5. Hoeveel pagina’s kan ik per dag van TripAdvisor scrapen?
Met één IP en nette vertragingen: grofweg 600–1.000 pagina’s per dag. Met 20 roterende residential proxies: ongeveer 200.000–300.000 pagina’s per dag met request-gebaseerde aanpakken. Selenium is trager — reken op 8.000–12.000 pagina’s per dag per proxy. De verborgen JSON/GraphQL-aanpak levert de meeste data per request op, dus je hebt vaak veel minder pagina’s nodig om dezelfde hoeveelheid informatie te verzamelen.
Meer lezen
