How to scrape tripadvisor cover

TripAdvisor adalah sumber informasi berharga bagi siapa pun yang ingin mendapatkan gambaran tentang kondisi terkini hotel, restoran, dan layanan terkait perjalanan lainnya. Portal ini memiliki lebih dari 1 miliar ulasan di 8 juta lokasi. Cukup mengesankan, bukan? 

Setiap hari, pengguna memberikan rating dan umpan balik, membandingkan harga, serta mencari destinasi. Hal ini menciptakan lapisan intelijen pasar yang terus diperbarui. TripAdvisor tidak hanya berguna bagi pelancong perorangan, tetapi juga bagi bisnis. Platform pemesanan dan perusahaan perjalanan melakukan web scraping data terstruktur dari TripAdvisor untuk memantau perubahan harga musiman, umpan balik, serta membandingkan penawaran dengan pesaing. Ini adalah cara yang baik untuk meninjau kembali dan menganalisis apakah strategi Anda berada di jalur yang tepat. 

Dengan mempertimbangkan hal tersebut, kami menyiapkan tutorial praktis ini yang akan berguna bagi siapa pun yang ingin mengetahui lebih banyak tentang TripAdvisor dan cara melakukan web scraping data yang tersedia untuk umum. 

*Web scraping harus selalu dilakukan dalam batas hukum dan etika. Kami tidak mendorong aktivitas ilegal dan hanya menyoroti strategi penggunaan yang bertanggung jawab.

Mengapa TripAdvisor begitu populer?

Saat merencanakan detail perjalanan atau sekadar mencari tren pasar, TripAdvisor muncul sebagai salah satu portal yang paling banyak dikunjungi di industri perjalanan. Portal ini penuh dengan opini publik yang relevan karena orang biasanya mengunggah foto dan video dari tempat yang telah dikunjungi atau acara yang dihadiri. Setiap orang dapat memberi rating dan ulasan untuk hotel serta akomodasi, memilih atraksi favorit, menyimpannya untuk nanti, dan banyak lagi. 

Pengguna dapat mengakses TripAdvisor dari perangkat apa pun, baik desktop maupun seluler. Filter dan kategori tersusun dengan jelas, sementara hasil disaring berdasarkan harga, rating, lokasi, atau fasilitas. Antarmuka TripAdvisor yang ramah pengguna juga menyediakan dashboard dan analitik bagi pemilik yang mengelola listing. Mereka mendapatkan akses ke fitur seperti metrik kinerja, ringkasan ulasan, dan statistik engagement.

*Apakah melakukan web scraping TripAdvisor legal?

Jawaban singkatnya, ya. Situs ini memuat data yang tersedia untuk umum, sehingga siapa pun dapat melakukan web scraping halaman tersebut untuk keperluannya. Bagian pentingnya adalah mematuhi kebijakan, seperti GDPR dan CCPA. 

Ingat: Anda tidak boleh menyimpan data pribadi atau mengakses situs web melalui bot karena hal itu melanggar Ketentuan Layanan TripAdvisor. Agar tetap aman, gunakan solusi tepercaya yang meniru perilaku manusia. Misalnya, di DataImpulse, kami menawarkan berbagai jenis proxy yang dapat membantu Anda melakukan web scraping konten di berbagai lokasi di seluruh dunia. Selain itu, proxy tersebut menawarkan kecepatan luar biasa dan keandalan terbaik.  

Metode 1. Mengumpulkan data menggunakan Python

Metode ini paling cocok bagi pengguna yang sudah mengenal Python dan memahami beberapa proses dasar. Jika tujuan Anda adalah pemrosesan data kustom atau operasi berskala besar, lanjutkan membaca untuk mengetahui cara memanfaatkan data TripAdvisor secara maksimal.

Persiapan Awal: Apa yang Perlu Diunduh?

  • Python 3 (versi terbaru)

Unduh di sini, instal ekstensi Python di VS Code. Buka terminal, lalu periksa apakah sudah terinstal dengan perintah berikut: 


python3 --version 
      
        
      

  • Visual Studio Code (atau editor kode lain, versi terbaru)

Unduh di sini, instal, lalu buka folder proyek Anda.

  • Kredensial proxy dari dashboard DataImpulse
  • Library: Selenium (+web driver), BeautifulSoup, Undetected-chromedriver. 

Selenium: mengotomatiskan browser dan memuat konten dinamis TripAdvisor.

BeautifulSoup: mengurai HTML yang telah dirender dan mengekstrak data restoran.

Undetected-chromedriver: membantu mengurangi deteksi otomatisasi.

*Cara mengonfigurasi Selenium di Python di sini

Instal library Python menggunakan:


pip3 install selenium beautifulsoup4 undetected-chromedriver 
      
        
      

Tekan Enter, lalu Anda akan melihat apakah library tersebut telah terinstal.

Langkah Umum untuk Melakukan Web Scraping TripAdvisor di Python

Banyak situs web menggunakan sistem keamanan seperti DataDome, dan TripAdvisor tidak terkecuali. Sistem ini diintegrasikan ke infrastruktur mereka untuk mendeteksi lalu lintas otomatis berbahaya dan melindungi data dari web scraping. Apa yang dapat kita lakukan dalam kasus ini? Kita akan menggunakan solusi yang menyerupai browser: Selenium dengan UndetectedChromedriver. 

Karena sistem DataDome memerlukan rendering JavaScript, script dijalankan dengan headless = False agar situs dapat dimuat dan dirender dengan benar.

Kode ini menggunakan format proxy hostname:port dan tidak mendukung proxy yang diautentikasi. Oleh karena itu, alamat IP harus dimasukkan ke whitelist agar proxy berfungsi dengan benar.

Seperti apa sisi teknisnya?

1. Tahap konfigurasi: tentukan URL yang akan dibuka, pilih lokasi penyimpanan file, putuskan apakah jendela browser akan ditampilkan, dan tentukan apakah akan menggunakan proxy.

2. Inisialisasi browser: program secara otomatis menjalankan Chrome, membuka halaman TripAdvisor, dan menunggu hingga hasil restoran dimuat sepenuhnya.

3. Penanganan interaksi dinamis: script mendeteksi dan mengklik tombol persetujuan cookie, lalu memicu tombol “Tampilkan lebih banyak” untuk memuat hasil tambahan.

4. Ekstraksi data: program mengumpulkan informasi untuk setiap restoran, termasuk nama, rating, jumlah ulasan, dan tautannya.

5. Serialisasi data: Semua data yang diekstrak disimpan dalam file bernama restaurants.json. File ini kemudian dapat digunakan untuk pemrosesan lanjutan, analitik, atau analisis tren.

Kita akan menggunakan URL ini dalam script kita, lalu mengekstrak nama, ulasan, dan rating. 

Ekstrak judul: 


title_from_href(href) 
      
        
      

Ekstrak ulasan:


m = re.search(r"([\d.,KkMm]+)\s+reviews", text) 
      
        
      

Ekstrak rating:


rating = extract_rating(card)  
      
        
      

Kode Lengkap

Setelah konfigurasi selesai, Anda dapat menjalankan script. Script tersebut akan menjalankan instance browser dan memperagakan bagaimana situs web dimuat serta beroperasi melalui proxy yang telah dikonfigurasi. 

*Untuk konfigurasi proxy, ganti hostname dan port dengan milik Anda dari dashboard DataImpulse. 

Contoh kami dalam praktik:


import json
import re
import time
from dataclasses import dataclass
from typing import Any, Optional

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

import undetected_chromedriver as uc
from bs4 import BeautifulSoup
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

SHOW_MORE_CLICKS = 1  # Number of "Show more" clicks should be 1

@dataclass(frozen=True)
class Config:
   url: str = "https://www.tripadvisor.com/Search?q=restaurants+in+new+york"
   output_json: str = "restaurants.json"
   headless: bool = False
   timeout_seconds: int = 30
   sleep_seconds: float = 2.5
   proxy: Optional[str] = "http://gw.dataimpulse.com:823"
   block_geolocation: bool = True

def first_number(text: Optional[str]) -> Optional[float]:
   """Extract first numeric value from text."""
   if not text:
       return None
   m = re.search(r"(\d+(?:[.,]\d+)?)", text)
   return float(m.group(1).replace(",", ".")) if m else None

def parse_reviews_count(text: Optional[str]) -> Optional[int]:
   """Parse review counts like '1,234', '1.2k', '3M'."""
   if not text:
       return None

   t = text.strip().lower()

   m = re.search(r"(\d+(?:[.,]\d+)?)\s*([km])\b", t)
   if m:
       val = first_number(m.group(0))
       if val is None:
           return None
       return int(val * (1_000 if m.group(2) == "k" else 1_000_000))

   m = re.search(r"(\d[\d, ]*)", t)
   if not m:
       return None

   digits = m.group(1).replace(",", "").replace(" ", "")
   return int(digits) if digits.isdigit() else None

def title_from_href(href: Optional[str]) -> Optional[str]:
   """Extract readable title from restaurant URL."""
   if not href:
       return None
   m = re.search(r"/Restaurant_Review-[^?#]*?-Reviews-([^-/?#]+)", href)
   return m.group(1).replace("_", " ").strip() if m else None

def rating_from_bubble_class(class_list: Optional[list[str]]) -> Optional[float]:
   """Extract rating from 'bubble_XX' CSS class."""
   if not class_list:
       return None
   for c in class_list:
       m = re.search(r"\bbubble_(\d{2})\b", c)
       if m:
           return int(m.group(1)) / 10.0
   return None

def extract_rating(card) -> Optional[float]:
   """Extract rating from aria-label, bubble class, or svg title."""
   el = card.select_one('[aria-label*="bubbles"]') or card.select_one('[aria-label*="of 5"]')
   if el:
       v = first_number(el.get("aria-label"))
       if v is not None:
           return v


   bubble = card.select_one(".ui_bubble_rating, [class*='bubble_']")
   if bubble:
       v = rating_from_bubble_class(bubble.get("class"))
       if v is not None:
           return v


   svg_title = card.select_one("svg title")
   if svg_title:
       v = first_number(svg_title.get_text(strip=True))
       if v is not None:
           return v


   return None

def build_driver(cfg: Config) -> uc.Chrome:
   """Create configured Chrome driver."""
   opts = uc.ChromeOptions()

   if cfg.headless:
       opts.add_argument("--headless=new")

   opts.add_argument("--window-size=1280,900")
   opts.add_argument("--disable-blink-features=AutomationControlled")


   if cfg.block_geolocation:
       prefs = {
           "profile.default_content_setting_values.geolocation": 2,
           "profile.default_content_setting_values.notifications": 2,
       }
       opts.add_experimental_option("prefs", prefs)


   if cfg.proxy:
       opts.add_argument(f"--proxy-server={cfg.proxy}")


   return uc.Chrome(options=opts)

def click_first(driver, xpaths: list[str]) -> bool:
   """Click first matching element from xpath list."""
   for xp in xpaths:
       try:
           driver.find_element(By.XPATH, xp).click()
           return True
       except Exception:
           continue
   return False


def get_html(cfg: Config) -> str:
   """Load page and return HTML after interactions."""
   driver: Optional[uc.Chrome] = None

   try:
       driver = build_driver(cfg)
       driver.get(cfg.url)


       WebDriverWait(driver, cfg.timeout_seconds).until(
           lambda d: d.find_elements(By.CSS_SELECTOR, 'a[href*="/Restaurant_Review-"]')
       )


       click_first(driver, [
           '//button[contains(., "Accept")]',
           '//button[contains(., "I accept")]',
           '//button[contains(., "Agree")]',
           '//button[contains(., "OK")]',
       ])


       time.sleep(cfg.sleep_seconds)


       for _ in range(max(0, SHOW_MORE_CLICKS)):
           if not click_first(driver, [
               '//button[contains(., "Show more")]',
               '//a[contains(., "Show more")]',
           ]):
               break
           time.sleep(cfg.sleep_seconds)


       return driver.page_source


   except (TimeoutException, WebDriverException) as e:
       raise RuntimeError(f"Page load failed: {e}") from e


   finally:
       if driver:
           driver.quit()

def parse_restaurants(html: str) -> list[dict[str, Any]]:
   """Parse restaurant cards into structured data."""
   soup = BeautifulSoup(html, "html.parser")


   cards = soup.select('[data-test-attribute="location-results-card"]')
   if not cards:
       cards = [a.parent for a in soup.select('a[href*="/Restaurant_Review-"]') if a.parent]


   results: list[dict[str, Any]] = []
   seen: set[str] = set()


   for card in cards:
       a = card.select_one('a[href*="/Restaurant_Review-"]')
       if not a:
           continue


       href = a.get("href")
       if not href:
           continue


       link = href if href.startswith("http") else f"https://www.tripadvisor.com{href}"
       if link in seen:
           continue
       seen.add(link)


       title = title_from_href(href) or a.get_text(strip=True) or None
       rating = extract_rating(card)


       text = card.get_text(" ", strip=True)
       m = re.search(r"([\d.,KkMm]+)\s+reviews", text)
       reviews = parse_reviews_count(m.group(1)) if m else None


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


   return results

def save_json(rows: list[dict[str, Any]], path: str) -> None:
   """Save data to JSON file."""
   with open(path, "w", encoding="utf-8") as f:
       json.dump(rows, f, ensure_ascii=False, indent=2)

def main() -> None:
   """Run scraping pipeline."""
   cfg = Config()
   html = get_html(cfg)
   rows = parse_restaurants(html)

   if not rows:
       print("No results found. Try running with headless=False.")
       return


   save_json(rows, cfg.output_json)
   print(f"Saved {len(rows)} restaurants to {cfg.output_json}")

if __name__ == "__main__":
   main()  
      
        
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
            
             
              
                 
         
          
           
      

Semua output disimpan ke file restaurants.json. File tersebut berisi:

  • Nama restoran
  • Rating
  • Jumlah ulasan
  • Tautan ke ulasan

Metode 2. Alternatif tanpa kode untuk pemula

Jika Anda memerlukan hasil cepat dan tidak ingin belajar pemrograman, metode ini dapat berguna bagi Anda. Scraper tanpa kode memberi Anda kesempatan untuk mendapatkan data yang dibutuhkan tanpa keterampilan coding. 

Apify adalah platform cloud dengan scraper siap pakai untuk banyak situs web, termasuk TripAdvisor. Platform ini memiliki paket gratis, dan paket berbayarnya biasanya dimulai sekitar $29/bulan. 

Baca selengkapnya tentang Apify → di sini.

Octoparse dikenal dengan antarmuka drag-and-drop dan pembuat alur kerja visualnya. Octoparse memiliki versi gratis, dengan paket berbayar mulai dari $69/bulan. 

Ingin mengetahui lebih banyak tentang Octoparse? Di sini jawabannya.

Web Scraper, ekstensi Chrome, memungkinkan Anda memilih elemen secara visual dan mengekstrak data. Ekstensi ini gratis, tetapi otomatisasi cloud dimulai sekitar $50/bulan. 

Integrasikan Web Scraper dengan proxy DataImpulse.

Untuk mengetahui lebih banyak web scraper tanpa kode yang bermanfaat, baca artikel. Secara keseluruhan, alat-alat ini meniadakan kebutuhan akan pemrograman, tetapi harga dan kemampuannya bervariasi tergantung jumlah data yang Anda perlukan serta kompleksitas situsnya.

Kiat bermanfaat dari tim DataImpulse

  1. Salah satu tantangannya adalah akses ke sumber dapat menjadi terbatas jika Anda mengirim request dari satu alamat IP. Oleh sebab itu, kami merekomendasikan untuk mencoba residential proxy kami. Mengapa? Karena residential proxy mengarahkan request melalui alamat IP yang berbeda-beda. Anda juga mendapatkan layanan berkeandalan tinggi, lalu lintas tanpa masa kedaluwarsa, dan dukungan nyata 24/7. 
  2. Selain menggunakan proxy, beri jeda antar-request, setidaknya 2-3 detik. 
  3. Jika Anda tiba-tiba mendapatkan error 429 (Terlalu banyak request), jangan langsung me-refresh halaman secara agresif. Tunggu sebentar, lalu coba lagi. 
  4. Gunakan TripAdvisor untuk tujuan yang sah. Jangan melakukan spam, pengumpulan data, atau penipuan. 
  5. Ikuti perkembangan hukum terbaru. 

Tutorial Terkait

*Tutorial ini semata-mata untuk tujuan pendidikan dan berfungsi sebagai demonstrasi kemampuan teknis. Penting untuk menyadari bahwa melakukan web scraping data dari TripAdvisor menimbulkan kekhawatiran terkait ketentuan penggunaan dan legalitas. Web scraping tanpa izin dapat menimbulkan konsekuensi serius, termasuk tindakan hukum dan penangguhan akun. Selalu lakukan dengan hati-hati dan ikuti pedoman etika.

Share article: