Forrige uke prøvde jeg å hente hotellvurderinger og antall anmeldelser for rundt 200 overnattingssteder i tre europeiske byer fra TripAdvisor. Det første skriptet mitt — en enkel requests.get() med standard headere — ga meg et pent 403 Forbidden på hver eneste forespørsel. Ikke en eneste byte med brukbar data.
TripAdvisor er en av de rikeste offentlige datakildene i reisebransjen: over , mer enn 8 millioner bedriftsoppføringer og rundt 460 millioner unike månedlige besøkende. Plattformen påvirker mer enn i årlige reiseutgifter. Men å hente disse dataene programmatisk? Der blir det fort komplisert. TripAdvisor bruker DataDome-botdeteksjon, Cloudflare WAF, TLS-fingerprinting og JavaScript-utfordringer — et lagdelt forsvar som stopper de fleste naive scraping-forsøk før de i det hele tatt kommer i gang. Denne guiden er ressursen jeg selv skulle ønske jeg hadde: en direkte sammenligning av tre Python-metoder for scraping (pluss et no-code-alternativ), komplett kode for hver metode, en strukturert feilsøkingsdel mot anti-bot-sperrer og gjenbrukbare mønstre som fungerer på tvers av hoteller, restauranter og attraksjoner. Enten du er nybegynner i Python eller en erfaren utvikler, bør dette spare deg for mange bortkastede 403-feil.
Vil du slippe å skrive kode? Scrape TripAdvisor på den enkle måten
Jeg vil være helt ærlig med en gang. Mange som søker etter "scrape TripAdvisor with Python" er egentlig ikke spesielt opptatt av å skrive kode. De vil bare ha dataene — hotellnavn, vurderinger, antall anmeldelser, priser — raskt og rett inn i et regneark. Hvis det høres ut som deg, finnes det en mye kortere vei.
er en AI-drevet Chrome-utvidelse vi har bygget som kan lese hvilken som helst TripAdvisor-side og automatisk foreslå hvilke kolonner som bør hentes ut. Arbeidsflyten er faktisk bare to klikk:
- Åpne en TripAdvisor-liste-side (for eksempel søkeresultatene for "Hotels in Paris").
- Klikk "AI Suggest Fields" i Thunderbit-sidepanelet. AI-en analyserer siden og foreslår kolonner som Hotel Name, Rating, Review Count, Price og Location.
- Klikk "Scrape." Thunderbit henter data fra hver oppføring på siden — og håndterer paginering automatisk hvis du trenger flere resultater.
- Eksporter til Excel, Google Sheets, Airtable eller Notion. Eksport er gratis på alle planer.
Thunderbit fungerer på tvers av hoteller, restauranter og attraksjoner uten at du må endre noe i oppsettet — AI-en tilpasser seg innholdet på siden. For sider med paginering oppdager den automatisk "Neste"-knapper og uendelig scrolling. Og fordi den kjører i din ekte Chrome-nettleser, bruker den dine eksisterende sesjonscookies og nettleserfingeravtrykk, noe som gir den en naturlig fordel mot botdeteksjon.
Du kan teste det med — gratisversjonen gir deg 6 sider per måned, nok til å teste arbeidsflyten.
Hvis du trenger programmatisk kontroll, egen parsingslogikk eller planlegger å scrape 10 000+ sider, er Python veien å gå. Fortsett å lese.
Hvorfor scrape TripAdvisor med Python?
TripAdvisor-data har direkte og målbar forretningsverdi. En fant at en økning på 1 poeng i et hotels Global Review Index på 100-poengsskalaen gir en økning på 0,89 % i gjennomsnittlig dagspris og 1,42 % i inntekt per tilgjengelig rom. En annen viste at en uavhengig økning på 1 stjerne i TripAdvisor-rating kan gi et gjennomsnittshotell 55 000–75 000 dollar i ekstra årlig inntekt. Anmeldelser er ikke bare en pyntemåling — de driver inntekter.
Slik bruker ulike team TripAdvisor-data:
| Brukstilfelle | Hvem har nytte av det | Data som trengs |
|---|---|---|
| Konkurrentanalyse for hotell | Hotellkjeder, revenue managers | Vurderinger, priser, antall anmeldelser, fasiliteter |
| Markedsanalyse for restaurant | Restaurantgrupper, matvaremerker | Kjøkkentype, prisklasser, stemning i anmeldelser |
| Sporing av attraksjonstrender | Turoperatører, turistkontorer | Popularitetsrangeringer, sesongmønstre |
| Sentimentanalyse | Forskere, dataanalytikere | Full tekst i anmeldelser, stjernevurderinger, datoer |
| Lead-generering | Salgsteam, reisebyråer | Bedriftsnavn, kontaktinformasjon, plasseringer |
Hvorfor akkurat Python? Tre grunner. Først økosystemet: BeautifulSoup, Selenium, Playwright, Scrapy, httpx, pandas — Python har mer modne biblioteker for scraping og dataanalyse enn noe annet språk. For det andre bruker Python, noe som betyr mer fellesskapsstøtte, flere svar på StackOverflow og mer oppdaterte guider. For det tredje fordelene i hele pipelinen: du kan scrape med BeautifulSoup, rydde data med pandas, kjøre sentimentanalyse med Hugging Face Transformers og bygge dashboards — alt i ett språk. Ingen hopping mellom verktøy.
Tre måter å scrape TripAdvisor med Python på (sammenlignet)
Alle sammenlignbare guider velger én metode og kjører på med den. Det hjelper ikke når du prøver å bestemme deg før du skriver kode. Her er sammenligningstabellen jeg skulle ønske noen hadde gitt meg:
| Metode | Hastighet | JS-støtte | Motstand mot anti-bot | Kompleksitet | Best for |
|---|---|---|---|---|---|
requests + BeautifulSoup | ⚡ Rask (~120–200 sider/min rått) | ❌ Ingen | ⚠️ Lav | Enkel | Statiske listesider, små prosjekter |
| Selenium / headless nettleser | 🐢 Sakte (~8–20 sider/min) | ✅ Full | ⚠️ Middels | Middels | Dynamisk innhold, "Read more"-klikk, cookie-bannere |
| Skjult JSON / GraphQL API | ⚡⚡ Raskest (~200–600 sider/min rått) | N/A | ✅ Høyere | Vanskelig | Stor skala for anmeldelser/hotelldata |
| No-code (Thunderbit) | ⚡ Rask | ✅ Innebygd | ✅ Innebygd | Enklest | Ikke-utviklere, raske engangseksporter |
Et par viktige forbehold. Disse rå hastighetene er teoretiske — TripAdvisors rate limits (~10–15 forespørsler per minutt per IP) begrenser faktisk gjennomstrømning til omtrent 10 sider/minutt per IP uansett metode. Den skjulte JSON-metoden gir deg mest data per forespørsel, som betyr færre totale forespørsler og mindre eksponering for rate limiting. Selenium er 5 ganger tregere enn request-baserte metoder i reelle tester, men er det eneste alternativet når du må klikke på knapper eller rendere JavaScript.
Resten av guiden går gjennom alle tre Python-metodene med full kode. Velg den som passer situasjonen din, eller kombiner dem (jeg bruker ofte requests+BS4 for listesider og skjult JSON for detaljsider).
Slik setter du opp Python-miljøet ditt
Før vi begynner, la oss gjøre miljøet klart. Du trenger Python 3.10+ (jeg anbefaler 3.12 eller 3.13 — alle store pakker støtter dem uten kjente problemer).
Installer alt på én gang:
1pip install requests beautifulsoup4 selenium httpx parsel pandas curl-cffi
Pakke-notater:
requests(2.33.1) — HTTP-forespørsler, krever Python 3.10+beautifulsoup4(4.14.3) — HTML-parsingselenium(4.43.0) — Nettleserautomatisering, krever Python 3.10+httpx(0.28.1) — Asynkron HTTP-klientparsel(1.11.0) — CSS/XPath-velgere (lettere enn BS4)pandas(3.0.2) — Eksport av data, krever Python 3.11+curl_cffi(0.15.0) — TLS-fingerprinting-imitasjon (kritisk for å komme rundt Cloudflare)
ChromeDriver: Hvis du bruker Selenium, er det gode nyheter — siden Selenium 4.6 laster Selenium Manager automatisk ned og cacher riktig ChromeDriver-binær. Du trenger ingen manuell installasjon. Versjonsmatching håndteres dynamisk, så du slipper å bekymre deg for mismatch mellom Chrome og driver.
Virtuelt miljø (anbefalt):
1python -m venv tripadvisor-scraper
2source tripadvisor-scraper/bin/activate # macOS/Linux
3tripadvisor-scraper\Scripts\activate # Windows
Metode 1: Scrape TripAdvisor med Requests og BeautifulSoup
Dette er den enkleste metoden. Den fungerer godt for listesider (hotellsøk, restaurantlister) der dataene du trenger allerede ligger i den statiske HTML-en. Ingen nettleser, ingen JavaScript-rendering, minimalt ressursforbruk.
Forstå TripAdvisor-URL-mønstrene
TripAdvisor-URL-er følger forutsigbare mønstre etter kategori:
- Hoteller:
https://www.tripadvisor.com/Hotels-g{locationId}-{Location_Name}-Hotels.html - Restauranter:
https://www.tripadvisor.com/Restaurants-g{locationId}-{Location_Name}.html - Attraksjoner:
https://www.tripadvisor.com/Attractions-g{locationId}-Activities-{Location_Name}.html
Paginering bruker parameteren oa (offset anchors) i URL-en. Hver side viser 30 resultater:
- Side 1: grunn-URL (uten
oa-parameter) - Side 2:
Hotels-g187768-oa30-Italy-Hotels.html - Side 3:
Hotels-g187768-oa60-Italy-Hotels.html
For anmeldelsessider er offset-parameteren or med trinn på 10:
- Side 1:
Reviews-or0-Hotel_Name.html - Side 2:
Reviews-or10-Hotel_Name.html
For å få anmeldelser på alle språk, legg til ?filterLang=ALL i URL-en.
Sende forespørsler med realistiske headere
TripAdvisor sjekker headere aggressivt. En forespørsel med standard Python-headere blir blokkert med én gang. Du må etterligne en ekte Chrome-nettleser:
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"Innholdslengde: {len(response.text)} tegn")
Viktig detalj: TripAdvisor validerer at User-Agent- og Sec-CH-UA-Client Hints-headere er konsistente. Hvis du hevder å være Chrome 135 i User-Agent, men Sec-CH-UA sier Chrome 120, blir du flagget. Rotér alltid hele header-sett sammen, ikke enkeltheadere hver for seg.
Parsing av lister med BeautifulSoup
Når du har et vellykket svar, trekker du ut dataene med BeautifulSoup. TripAdvisor bruker data-automation- og data-test-attribute-attributter som er mer stabile enn CSS-klassenavn (som endrer seg ofte):
1from bs4 import BeautifulSoup
2soup = BeautifulSoup(response.text, "html.parser")
3# Finn alle hotellkortene
4cards = soup.select('div[data-test-attribute="location-results-card"]')
5hotels = []
6for card in cards:
7 # Hotellnavn
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 # Lenke til detaljside
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 # Vurdering
14 rating_el = card.select_one('[data-automation="bubbleRatingValue"]')
15 rating = rating_el.get_text(strip=True) if rating_el else None
16 # Antall anmeldelser
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"Fant {len(hotels)} hoteller på denne siden")
26for h in hotels[:3]:
27 print(h)
Et ord om velgere: TripAdvisor bruker obfuskerte CSS-klassenavn (som FGwzt, yyzcQ) som endrer seg ved hver oppdatering av nettstedet. data-automation- og data-test-target-attributtene er langt mer stabile. Foretrekk alltid data-attributter fremfor klassenavn.
Håndtering av paginering
For å scrape flere sider kan du loope gjennom offset-parameteren med en rolig pause mellom forespørslene:
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): # Første 5 sider
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"Side {page + 1}: Fikk status {response.status_code}, stopper.")
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"Side {page + 1}: fant {len(cards)} hoteller")
22 time.sleep(random.uniform(3, 7)) # Tilfeldig pause for å unngå rate limiting
23df = pd.DataFrame(all_hotels)
24print(f"\nTotalt antall hoteller scraped: {len(df)}")
time.sleep(random.uniform(3, 7)) er viktig. TripAdvisors terskel for rate limiting er omtrent 10–15 forespørsler per minutt per IP. Går du fortere enn det, utløses ofte CAPTCHA eller 429-feil.
Begrensninger ved denne metoden
Hvor faller dette fra hverandre? Requests+BS4-metoden feiler når:
- TripAdvisor serverer JavaScript-rendret innhold (noen søkeresultatsider krever JS)
- Anmeldelsestekst er forkortet bak "Read more"-knapper
- Anti-bot-mekanismene eskalerer til JavaScript-utfordringer eller CAPTCHA-er
- Du trenger data som bare dukker opp etter client-side rendering (priser, tilgjengelighet)
For disse situasjonene trenger du enten Selenium (Metode 2) eller den skjulte JSON-metoden (Metode 3).
Metode 2: Scrape TripAdvisor med Selenium (headless nettleser)
Selenium starter en ekte nettleser, som betyr at den kan rendere JavaScript, klikke på knapper, håndtere cookie-samtykke og samhandle med dynamisk innhold. Prisen: den er omtrent og bruker 300–500 MB RAM per nettleserinstans.
Konfigurere Selenium med anti-deteksjonsinnstillinger
Rett ut av boksen er Selenium lett å oppdage. TripAdvisors fingerprinting fanger det opp umiddelbart. Du må deaktivere automasjonsflagg:
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") # Bruk ny headless-modus (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# Fjern webdriver-egenskapen fra navigator
15driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
16 "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
17})
Er dette nok for TripAdvisor? For scraping i liten skala (under 50 sider) fungerer dette oppsettet som regel med residential proxies. For større volum kan du trenge undetected-chromedriver eller nodriver — TripAdvisors DataDome-beskyttelse analyserer over 1 000 signaler per forespørsel, inkludert TLS-fingerprints som vanlig Selenium ikke kan forfalske.
Scrape hotellsøkeresultater med Selenium
1import time
2import random
3url = "https://www.tripadvisor.com/Hotels-g187147-Paris_Ile_de_France-Hotels.html"
4driver.get(url)
5# Vent til hotellkortene er lastet
6wait = WebDriverWait(driver, 15)
7wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-test-attribute="location-results-card"]')))
8# Håndter cookie-popup hvis den dukker opp
9try:
10 cookie_btn = driver.find_element(By.ID, "onetrust-accept-btn-handler")
11 cookie_btn.click()
12 time.sleep(1)
13except:
14 pass # Ingen cookie-popup
15# Hent hotell-data
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"Scrapet {len(hotels)} hoteller")
33for h in hotels[:3]:
34 print(h)
Dette tok omtrent 8 sekunder for én side på maskinen min — sammenlignet med under 1 sekund med requests+BS4. Den 8x forskjellen blir fort stor når du scraper hundrevis av sider.
Utvide "Read more" og hente fulle anmeldelser
Anmeldelsessider forkorter lange anmeldelser bak en "Read more"-knapp. Selenium kan klikke på den:
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# Klikk alle "Read more"-knappene
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# Hent anmeldelser
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 # Vurdering er kodet i klassen, for eksempel "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"Scrapet {len(reviews)} anmeldelser")
Legge til proxy-rotasjon i Selenium
For vedvarende scraping trenger du proxy-rotasjon. Siden selenium-wire har vært avviklet siden januar 2024, bør du bruke Chromes innebygde proxy-støtte:
1# Med proxy uten autentisering
2proxy = "http://your-proxy-address:port"
3options.add_argument(f"--proxy-server={proxy}")
4# For proxyer med autentisering må du bruke en Chrome-utvidelse eller Selenium 4s BiDi-protokoll
For programmatisk rotering av proxyer kan du opprette en ny driverinstans med en annen proxy for hver batch med forespørsler. Det er ikke elegant, men det er pålitelig.
Metode 3: Den skjulte JSON-metoden (dropp HTML-parsing helt)
De fleste guider hopper helt over denne metoden, og det er synd — den er den raskeste og reneste av de tre. TripAdvisor legger inn strukturert data som JSON direkte i HTML-sidene sine — inne i <script>-tagger som JavaScript-variabler som pageManifest og urqlCache. Når du henter ut denne JSON-en, får du renere data (vurderinger som tall, datoer i ISO-format) med færre forespørsler og uten behov for JavaScript-rendering.
Finne den innebygde JSON-en i sidens kilde
Nøkkelinnsikten: du kan bruke en enkel requests.get() til å hente siden og så trekke ut JSON-en fra rå HTML uten å rendere JavaScript i det hele tatt.
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# Hent ut JSON-blokken pageManifest
16match = re.search(r"pageManifest:({.+?})};", response.text)
17if match:
18 page_data = json.loads(match.group(1))
19 print("Fant pageManifest-data")
20 print(f"Nøkler: {list(page_data.keys())[:10]}")
Hvordan finne variabelnavnet selv: Åpne en hvilken som helst TripAdvisor-hotellside i Chrome, høyreklikk → Vis sidekilde, og søk med Ctrl+F etter pageManifest eller urqlCache eller aggregateRating. Dataene ligger der og venter på å bli hentet ut.
Parse JSON og hent strukturert data
TripAdvisor legger også inn schema.org-data i application/ld+json, og det er enda enklere å hente ut:
1from parsel import Selector
2sel = Selector(text=response.text)
3# Hent JSON-LD strukturert data
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"Navn: {data.get('name')}")
9 print(f"Vurdering: {data.get('aggregateRating', {}).get('ratingValue')}")
10 print(f"Antall anmeldelser: {data.get('aggregateRating', {}).get('reviewCount')}")
11 print(f"Prisklasse: {data.get('priceRange')}")
12 print(f"Adresse: {data.get('address', {}).get('streetAddress')}")
13 print(f"Koordinater: {data.get('geo', {}).get('latitude')}, {data.get('geo', {}).get('longitude')}")
14 break
JSON-LD-dataene ligger i den statiske HTML-en og krever IKKE JavaScript-rendering. De gir deg navn på eiendommen, samlet vurdering, antall anmeldelser, adresse, koordinater, prisklasse og bilde-URL-er — alt uten å parse en eneste HTML-tag.
For rikere data (enkeltanmeldelser, vurderingsfordeling, fasilitetslister) trenger du urqlCache-objektet:
1# Hent urqlCache for detaljert anmeldelsesdata
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 # Naviger i cachen for å finne anmeldelsesdata
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"Fant cache-oppføring for anmeldelser: {key[:50]}...")
11 break
De eksakte JSON-stiene endrer seg av og til når TripAdvisor oppdaterer frontend-en, men den overordnede strukturen — JSON-LD for oppsummeringsdata og urqlCache for detaljdata — har vært stabil i mange år.
Reverse-engineering av TripAdvisors GraphQL API (avansert)
For storskala uthenting returnerer TripAdvisors GraphQL-endepunkter strukturert data direkte. Dette er den raskeste metoden, men den krever også mest vedlikehold.
1import httpx
2import random
3import string
4def generate_request_id():
5 """Generer verdien for X-Requested-By-headeren"""
6 random_chars = ''.join(random.choices(string.ascii_letters + string.digits, k=180))
7 return f"TNI1625!{random_chars}"
8# Søk etter hoteller i Paris
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-forespørsel feilet: {response.status_code}")
For å hente anmeldelser 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"Totalt antall anmeldelser: {total}")
28 for r in reviews[:3]:
29 print(f" [{r['rating']}/5] {r['title']} - {r['createdDate']}")
Viktig forbehold: preRegisteredQueryId-verdiene (som 84b17ed122fbdbd4 for søk og ef1a9f94012220d3 for anmeldelser) kan slutte å virke når TripAdvisor ruller ut nye versjoner. Når det skjer, vil forespørslene dine feile stille. Du må finne query-ID-ene på nytt ved å overvåke nettverksforespørsler i browser DevTools.
Hvorfor denne metoden reduserer behovet for proxyer
Matematikk er enkel. Med requests+BS4 krever scraping av 100 hotellsider 100 forespørsler. Med den skjulte JSON-metoden får du alt du trenger fra én sideinnlasting per forespørsel — ingen ekstra forespørsler for å utvide anmeldelser eller laste dynamisk innhold. Med GraphQL kan ett API-kall returnere 20 anmeldelser samtidig. Færre forespørsler = mindre eksponering for rate limiting = mindre behov for proxy-rotasjon. For små til mellomstore prosjekter (under 1 000 sider) kan du kanskje klare deg uten proxies hvis du legger inn fornuftige pauser.
Scrape hoteller, restauranter og attraksjoner med ett gjenbrukbart skript
Fire av fem konkurrerende guider dekker bare hoteller. Men TripAdvisor har tre sentrale innholdskategorier, og URL-mønstrene og datafeltene varierer mellom dem. Slik bygger du én funksjon som håndterer alle tre.
Datfelter tilgjengelig per kategori
| Felt | Hoteller | Restauranter | Attraksjoner |
|---|---|---|---|
| Navn | ✅ | ✅ | ✅ |
| Vurdering | ✅ | ✅ | ✅ |
| Antall anmeldelser | ✅ | ✅ | ✅ |
| Pris/prisklasse | ✅ | ✅ | Noen ganger |
| Adresse | ✅ | ✅ | ✅ |
| Kjøkkentype | ❌ | ✅ | ❌ |
| Varighet/type tur | ❌ | ❌ | ✅ |
| Fasiliteter | ✅ | ❌ | ❌ |
| Koordinater | ✅ | ✅ | ✅ |
Bygge en gjenbrukbar scrape_tripadvisor()-funksjon
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 Scraper TripAdvisor-lister for hoteller, restauranter eller attraksjoner.
11 Args:
12 category: "hotels", "restaurants" eller "attractions"
13 location_id: TripAdvisor geo-ID (for eksempel "187147" for Paris)
14 location_name: URL-vennlig navn (for eksempel "Paris_Ile_de_France")
15 num_pages: Antall sider som skal scrapes
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" Side {page + 1}: Status {response.status_code}, stopper.")
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" Side {page + 1}: fant {len(cards)} elementer")
61 time.sleep(random.uniform(3, 7))
62 return pd.DataFrame(all_items)
63# Eksempler på bruk
64print("=== Hoteller i Paris ===")
65hotels_df = scrape_tripadvisor("hotels", "187147", "Paris_Ile_de_France", num_pages=2)
66print(hotels_df.head())
67print("\n=== Restauranter i Roma ===")
68restaurants_df = scrape_tripadvisor("restaurants", "187791", "Rome_Lazio", num_pages=2)
69print(restaurants_df.head())
70print("\n=== Attraksjoner i Barcelona ===")
71attractions_df = scrape_tripadvisor("attractions", "187497", "Barcelona_Catalonia", num_pages=2)
72print(attractions_df.head())
Én funksjon, tre kategorier, null kode-duplisering. Hvis TripAdvisor endrer en selektor, fikser du det på ett sted.
Hva du skal gjøre når TripAdvisor blokkerer deg (feilsøking mot anti-bot)
Dette er delen jeg selv trengte mest da jeg begynte å scrape TripAdvisor, og det er delen ingen konkurrerende guide gir på en strukturert måte. TripAdvisor bruker DataDome (som analyserer per dag) og Cloudflare WAF sammen. Her er en diagnose-tabell for de vanligste feilmodusene:
| Symptom | Sannsynlig årsak | Løsning |
|---|---|---|
| HTTP 403-svar | Manglende eller mistenkelige headere; Cloudflare JS-utfordring | Sett realistiske User-Agent, Accept-Language, Referer og Sec-CH-UA-headere. Sørg for at headere er konsistente. |
| CAPTCHA-side i stedet for data | Rate limiting eller nettleserfingerprinting | Rotér residential proxies, legg inn tilfeldige pauser (2–7 sekunder mellom forespørsler) |
| Tom HTML eller blank sidekropp | JavaScript ikke rendret av requests | Bytt til Selenium eller hent data fra skjult JSON i sidekilden |
| Delvise anmeldelser / "Read more" åpnes ikke | Innhold lastes ved klikkhendelse | Bruk Selenium med .click() eller hent fra innebygd JSON-blokk |
| Anmeldelser bare på ett språk | Mangler språkparameter | Legg til ?filterLang=ALL i anmeldelses-URL-en |
| Data slutter å laste etter N sider | Sesjonsbasert rate limit | Rotér sesjoner, tøm cookies mellom batcher |
| HTTP 1020 Access Denied | IP/ASN blokkert av Cloudflare | Bytt fra datacenter-proxyer til residential proxyer |
| Utfordringssløyfe (uendelig CAPTCHA) | Ødelagt cookie-persistens | Varm opp sesjoner ved å besøke startsiden først; behold cookie-jar |
Retry-logikk med eksponentiell backoff
Ingen konkurrerende artikkel viser faktisk denne koden. Her er en gjenbrukbar retry-funksjon:
1import time
2import random
3import requests
4def fetch_with_retry(session, url, max_retries=4, base_delay=2, max_delay=60):
5 """
6 Hent en URL med eksponentiell backoff og jitter.
7 Roterer User-Agent ved hvert forsøk.
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 # Roter User-Agent ved nytt forsøk
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 # Respekter Retry-After-header hvis den finnes
25 retry_after = int(response.headers.get("Retry-After", base_delay * (2 ** attempt)))
26 print(f" Rate limit (429). Venter {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" Fikk {response.status_code}. Forsøk {attempt + 1}/{max_retries} om {wait:.1f}s...")
32 time.sleep(wait)
33 continue
34 # Andre feilkoder — ikke retry
35 print(f" Uventet status {response.status_code} for {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. Forsøk {attempt + 1}/{max_retries} om {wait:.1f}s...")
40 time.sleep(wait)
41 print(f" Alle {max_retries} forsøk er brukt opp for {url}")
42 return None
Rotere headere, proxyer og sesjoner
For vedvarende scraping bør du holde en pool av header-sett og rotere dem samlet:
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 # Legg til flere residential proxies
23]
24def get_rotated_session():
25 """Opprett en ny sesjon med roterte headere og proxy."""
26 session = requests.Session()
27 # Velg et tilfeldig header-sett
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 # Velg en tilfeldig proxy
41 if PROXY_LIST:
42 proxy = random.choice(PROXY_LIST)
43 session.proxies = {"http": proxy, "https": proxy}
44 return session
Proxy-type betyr mye. Datacenter-proxyer blir blokkert nesten umiddelbart av TripAdvisor (HTTP 1020 Access Denied). Residential proxies er i praksis et krav for vedvarende scraping — de går via vanlige internettleverandører og er nærmest umulig å skille fra ekte brukere. Regn med å betale 2,50–8,40 dollar per GB, avhengig av leverandøren.
Eksportere og lagre TripAdvisor-dataene dine
Når du har dataene, er det enkelt å få dem inn i et format som kan brukes.
CSV-eksport (vanligst)
1import pandas as pd
2df = pd.DataFrame(all_hotels)
3df.to_csv("tripadvisor_hotels_paris.csv", index=False, encoding="utf-8-sig")
4print(f"Eksporterte {len(df)} rader til CSV")
encoding='utf-8-sig' er viktig — den sørger for at Excel viser ikke-latinske tegn riktig (franske aksenter, kinesiske tegn osv.) når CSV-filen åpnes.
JSON-eksport (for nestede data)
Når du har anmeldelser nestet under hoteller, bevarer JSON hierarkiet:
1# Hierarkisk struktur
2hotel_data = {
3 "property_id": "d194317",
4 "name": "NH City Centre Amsterdam",
5 "rating": 4.0,
6 "reviews": [
7 {"title": "Great location", "rating": 5, "date": "2025-03-15", "text": "..."},
8 {"title": "Average stay", "rating": 3, "date": "2025-03-10", "text": "..."},
9 ]
10}
11# For flat analyse, bruk 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)
To-fil-strategi for relasjonsdata
For store datasett bruker jeg to CSV-filer:
hotels.csv— én rad per overnattingssted (flat)reviews.csv— én rad per anmeldelse, medproperty_idsom fremmednøkkel
Dette gjør det enkelt å koble sammen data i pandas, laste dem inn i en database eller importere dem i BI-verktøy.
Hvis du ikke vil styre med alt dette eksportopplegget, lar Thunderbit deg til Excel, Google Sheets, Airtable eller Notion — helt gratis og uten kode. Nyttig når du skal dele resultatene med kolleger som ikke er tekniske.
Tips for ansvarlig og effektiv scraping av TripAdvisor
Ansvarlig scraping i seks punkt:
- Sjekk
robots.txt: TripAdvisors robots.txt blokkerer AI-treningsroboter (GPTBot, ClaudeBot osv.) helt. Vanlige crawlere møter selektive begrensninger på enkelte stier. Se påtripadvisor.com/robots.txt. - Legg inn pauser: 3–7 sekunder mellom forespørsler er et trygt intervall. Går du raskere enn 10–15 forespørsler per minutt per IP, utløses ofte rate limiting.
- Scrape bare offentlig data. Ikke logg inn for å hente beskyttet innhold.
- Lagre data sikkert og overhold GDPR/CCPA hvis du håndterer personopplysninger (for eksempel navn på anmeldere).
- Vurder TripAdvisors offisielle API hvis du trenger data i kommersiell skala. gir tilgang til bedriftsdetaljer pluss opptil 5 anmeldelser og 5 bilder per sted — begrenset, men lovlig og stabilt.
- Vær klar over den juridiske konteksten: styrket forbud mot scraping basert på vilkår i EU. TripAdvisors bruksvilkår forbyr eksplisitt scraping. Scrape ansvarlig og på eget ansvar.
Avslutning
Der har du helhetsbildet.
- Requests + BeautifulSoup er den enkleste veien. Den fungerer for statiske listesider, krever minimal oppsett og er rask. Start her hvis du scraper færre enn 100 sider og ikke trenger JavaScript-rendret innhold.
- Selenium håndterer alt requests ikke klarer: dynamisk innhold, "Read more"-knapper og cookie-bannere. Den er 5 ganger tregere og mer ressurskrevende, men er det eneste alternativet når du må samhandle med siden.
- Skjult JSON / GraphQL er den reneste og raskeste metoden. Den gir strukturert data uten HTML-parsing, reduserer antall forespørsler (og dermed behovet for proxies) og returnerer data i et format klart for analyse. Den krever mer reverse-engineering i starten og litt vedlikehold når TripAdvisor endrer datastrukturen.
Den gjenbrukbare scrape_tripadvisor()-funksjonen dekker hoteller, restauranter og attraksjoner. Du skal egentlig ikke trenge en ny veiledning.
Og hvis du underveis bestemmer deg for at koding ikke er noe for deg — eller du bare trenger 50 hoteller i et regneark innen arbeidsdagens slutt — kan gjøre det med to klikk, med AI-basert feltdeteksjon, automatisk paginering og gratis eksport til Excel eller Google Sheets. Ingen Python kreves.
Hvis du vil gå dypere, har vi flere scraping-veiledninger på og .
Vanlige spørsmål
1. Er det lov å scrape TripAdvisor?
TripAdvisors bruksvilkår forbyr eksplisitt scraping. Samtidig har domstoler som regel vurdert at scraping av offentlig tilgjengelige data (ikke bak innlogging) ikke bryter den amerikanske Computer Fraud and Abuse Act. Når det er sagt, styrket EU-domstolens Ryanair-avgjørelse i 2025 begrensninger basert på bruksvilkår i Europa. Scrape bare offentlig data, respekter robots.txt, ikke republiser opphavsrettsbeskyttet innhold, og rådfør deg med juridisk ekspertise hvis du skal bruke dataene kommersielt.
2. Kan jeg scrape TripAdvisor uten Python?
Ja. No-code-verktøy som kan scrape TripAdvisor direkte fra nettleseren din med AI-drevet feltdeteksjon og automatisk paginering. Du kan også bruke nettleserutvidelser, Google Sheets-tillegg eller kommersielle scraping-API-er. Python gir deg mest kontroll og fleksibilitet, men det er ikke det eneste alternativet.
3. Hvordan unngår jeg å bli blokkert når jeg scraper TripAdvisor?
De viktigste taktikkene: bruk realistiske og konsistente headere (særlig User-Agent og Sec-CH-UA), roter residential proxies (datacenter-IP-er blir blokkert med en gang), legg inn tilfeldige pauser på 3–7 sekunder mellom forespørsler, bruk den skjulte JSON-metoden for å redusere totalt antall forespørsler, implementer retry-logikk med eksponentiell backoff, og varm opp sesjoner ved å besøke startsiden før du scraper dypere sider.
4. Hvilke data kan jeg hente fra TripAdvisor?
Hoteller, restauranter og attraksjoner — inkludert navn, vurderinger, antall anmeldelser, prisklasser, adresser, koordinater, fasiliteter (hoteller), kjøkkentyper (restauranter), turvarighet (attraksjoner) og full anmeldelsestekst med individuelle vurderinger og datoer. Den skjulte JSON- og GraphQL-metoden gir det rikeste datamaterialet per forespørsel.
5. Hvor mange sider kan jeg scrape fra TripAdvisor per dag?
Med én IP og fornuftige pauser: omtrent 600–1 000 sider per dag. Med 20 roterende residential proxies: omtrent 200 000–300 000 sider per dag med request-baserte metoder. Selenium er tregere — regn med 8 000–12 000 sider per dag per proxy. Den skjulte JSON-/GraphQL-metoden gir mest data per forespørsel, så du kan ofte trenge langt færre sider for å få samme mengde informasjon.
Les mer