Perché Scrape Product Reviews a Scale?
Le recensioni dei prodotti sono una delle fonti di dati più preziose nell'e-commerce. Essi rivelano il sentimento del cliente, problemi di qualità del prodotto, richieste di funzionalità e posizionamento competitivo — informazioni che nessun'altra fonte di dati può fornire. In scala, i dati di revisione consentono:
- Analisi del sentimento: Traccia come i clienti si sentono circa i vostri prodotti e prodotti concorrenti nel tempo.
- Sviluppo del prodotto: Identificare reclami ricorrenti e richieste di funzionalità attraverso migliaia di recensioni.
- Intelligenza competitiva: Comprendere i punti di forza e di debolezza dei concorrenti dalle parole dei propri clienti.
- Ricerca di mercato: Scopri le esigenze e le tendenze emergenti analizzando i modelli di revisione in tutte le categorie.
- Monitoraggio della qualità: Rileva i problemi di qualità del prodotto in anticipo monitorando le tendenze del sentimento di recensione.
La sfida è che i dati di revisione sono diffusi su più piattaforme (Amazon, Walmart, Best Buy, Trustpilot, Google), ognuna con diverse strutture e protezioni anti-bot. Scraping recensioni su scala richiede strategie specifiche della piattaforma e robuste infrastrutture proxy. Per i modelli di raschiamento e-commerce fondamentali, vedere il nostro e-commerce dati scraping guida.
Review Data Structure Across Platforms
| Piattaforma | Campi di valutazione | Pagina | Livello Anti-Bot |
|---|---|---|---|
| Amazon | Rating, titolo, testo, data, verificato, voti utili | Pagina-based (10/pagina) | Alto |
| Walmart | Rating, titolo, testo, data, fonte di presentazione | API basata su offset | Media |
| Migliore acquisto | Valutazione, titolo, testo, data, utile/non utile | API basata sulla pagina | Media |
| Trustpilot | Voto, titolo, testo, data, risposta | Sulla base di pagine | Basso medio |
| Google Shopping | Valutazione, testo, data, sorgente | Scroll-based | Alto |
Configurazione proxy per Scraping Review
Il raschiamento della recensione comporta la navigazione impaginata, il che significa mantenere le sessioni attraverso più richieste. Le sessioni appiccicose di ProxyHat sono ideali per questo modello.
Impostazione ProxyHat
# Per-request rotation for initial product lookups
http://USERNAME:PASSWORD@gate.proxyhat.com:8080
# Sticky session for paginating through reviews of one product
http://USERNAME-session-rev001:PASSWORD@gate.proxyhat.com:8080
# Geo-targeted for region-specific review pages
http://USERNAME-country-US:PASSWORD@gate.proxyhat.com:8080Per la revisione demolizione, utilizzare sessioni appiccicose quando impaginare attraverso tutte le recensioni per un singolo prodotto, e per-richiesta rotazione quando si sposta tra diversi prodotti. Questo imita il comportamento di navigazione naturale in cui un utente legge più pagine di recensioni per un prodotto prima di passare al successivo.
Attuazione di Python
Ecco un raschietto di revisione multi-piattaforma utilizzando ProxyHat Python SDK.
Recensione di Amazon
import requests
from bs4 import BeautifulSoup
import json
import time
import random
from dataclasses import dataclass
from datetime import datetime
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
]
@dataclass
class Review:
platform: str
product_id: str
rating: float
title: str
text: str
date: str
author: str
verified: bool
helpful_votes: int
def scrape_amazon_reviews(asin, max_pages=10):
"""Scrape all reviews for an Amazon product."""
reviews = []
session_id = f"rev-{asin}-{random.randint(1000, 9999)}"
proxy = f"http://USERNAME-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
session = requests.Session()
session.proxies = {"http": proxy, "https": proxy}
session.headers.update({
"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
})
for page in range(1, max_pages + 1):
url = (f"https://www.amazon.com/product-reviews/{asin}"
f"?pageNumber={page}&sortBy=recent")
try:
response = session.get(url, timeout=30)
if response.status_code != 200:
break
if "captcha" in response.text.lower():
print(f"CAPTCHA on page {page}, switching session")
break
soup = BeautifulSoup(response.text, "html.parser")
review_divs = soup.find_all("div", {"data-hook": "review"})
if not review_divs:
break
for div in review_divs:
review = parse_amazon_review(div, asin)
if review:
reviews.append(review)
print(f"Page {page}: {len(review_divs)} reviews (total: {len(reviews)})")
time.sleep(random.uniform(2, 5))
except requests.RequestException as e:
print(f"Error on page {page}: {e}")
break
return reviews
def parse_amazon_review(div, asin):
"""Parse a single Amazon review element."""
try:
rating_el = div.find("i", {"data-hook": "review-star-rating"})
rating = float(rating_el.get_text().split(" ")[0]) if rating_el else None
title_el = div.find("a", {"data-hook": "review-title"})
title = title_el.get_text(strip=True) if title_el else ""
body_el = div.find("span", {"data-hook": "review-body"})
text = body_el.get_text(strip=True) if body_el else ""
date_el = div.find("span", {"data-hook": "review-date"})
date_str = date_el.get_text(strip=True) if date_el else ""
author_el = div.find("span", {"class": "a-profile-name"})
author = author_el.get_text(strip=True) if author_el else ""
verified = bool(div.find("span", {"data-hook": "avp-badge"}))
helpful_el = div.find("span", {"data-hook": "helpful-vote-statement"})
helpful = 0
if helpful_el:
text_h = helpful_el.get_text()
if "one" in text_h.lower():
helpful = 1
else:
nums = [int(s) for s in text_h.split() if s.isdigit()]
helpful = nums[0] if nums else 0
return Review(
platform="amazon",
product_id=asin,
rating=rating,
title=title,
text=text,
date=date_str,
author=author,
verified=verified,
helpful_votes=helpful,
)
except Exception:
return NoneMulti-Platform Review Collector
class ReviewCollector:
"""Collect reviews from multiple platforms for a product."""
def __init__(self):
self.scrapers = {
"amazon": scrape_amazon_reviews,
}
def collect_all(self, product_ids: dict) -> list[Review]:
"""
Collect reviews from all platforms.
product_ids: {"amazon": "B0CHX3QBCH", "walmart": "12345"}
"""
all_reviews = []
for platform, product_id in product_ids.items():
if platform in self.scrapers:
print(f"\nScraping {platform} reviews for {product_id}")
reviews = self.scrapers[platform](product_id)
all_reviews.extend(reviews)
print(f"Collected {len(reviews)} reviews from {platform}")
time.sleep(random.uniform(5, 10))
return all_reviews
def to_dataframe(self, reviews: list[Review]):
"""Convert reviews to a pandas DataFrame for analysis."""
import pandas as pd
return pd.DataFrame([vars(r) for r in reviews])
# Usage
collector = ReviewCollector()
reviews = collector.collect_all({
"amazon": "B0CHX3QBCH",
})
print(f"\nTotal reviews collected: {len(reviews)}")Node.js Attuazione
Un raschietto di revisione Node.js utilizzando SDK del nodo di ProxyHat.
const axios = require("axios");
const cheerio = require("cheerio");
const { HttpsProxyAgent } = require("https-proxy-agent");
function getProxy(sessionId = null) {
if (sessionId) {
return `http://USERNAME-session-${sessionId}:PASSWORD@gate.proxyhat.com:8080`;
}
return "http://USERNAME:PASSWORD@gate.proxyhat.com:8080";
}
async function scrapeAmazonReviews(asin, maxPages = 10) {
const reviews = [];
const sessionId = `rev-${asin}-${Math.floor(Math.random() * 9000 + 1000)}`;
const agent = new HttpsProxyAgent(getProxy(sessionId));
for (let page = 1; page <= maxPages; page++) {
const url = `https://www.amazon.com/product-reviews/${asin}?pageNumber=${page}&sortBy=recent`;
try {
const { data } = await axios.get(url, {
httpsAgent: agent,
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
},
timeout: 30000,
});
if (data.toLowerCase().includes("captcha")) {
console.log(`CAPTCHA on page ${page}`);
break;
}
const $ = cheerio.load(data);
const reviewDivs = $('[data-hook="review"]');
if (reviewDivs.length === 0) break;
reviewDivs.each((_, el) => {
const $el = $(el);
const ratingText = $el.find('[data-hook="review-star-rating"]').text();
const rating = parseFloat(ratingText.split(" ")[0]) || null;
reviews.push({
platform: "amazon",
productId: asin,
rating,
title: $el.find('[data-hook="review-title"]').text().trim(),
text: $el.find('[data-hook="review-body"]').text().trim(),
date: $el.find('[data-hook="review-date"]').text().trim(),
author: $el.find(".a-profile-name").text().trim(),
verified: $el.find('[data-hook="avp-badge"]').length > 0,
});
});
console.log(`Page ${page}: ${reviewDivs.length} reviews (total: ${reviews.length})`);
await new Promise((r) => setTimeout(r, 2000 + Math.random() * 3000));
} catch (err) {
console.error(`Error page ${page}: ${err.message}`);
break;
}
}
return reviews;
}
// Usage
scrapeAmazonReviews("B0CHX3QBCH", 5).then((reviews) => {
console.log(`Collected ${reviews.length} reviews`);
console.log(JSON.stringify(reviews.slice(0, 2), null, 2));
});Handling Pagination alla Scala
La paginazione della recensione è una delle sfide più grandi nella demolizione di recensioni su larga scala.
Strategia di Paginazione Amazon
Amazon limita le pagine di revisione a 10 recensioni ciascuna e tipicamente mostra fino a 500 pagine (5.000 recensioni). Per i prodotti con più recensioni, utilizzare i parametri del filtro per segmentare:
# Filter by star rating to get more reviews
star_filters = [
"one_star", "two_star", "three_star",
"four_star", "five_star"
]
for star in star_filters:
url = (f"https://www.amazon.com/product-reviews/{asin}"
f"?filterByStar={star}&pageNumber={page}")
# This lets you access more reviews per productGestione delle sessioni per Paginazione
Ogni paginazione di recensione del prodotto dovrebbe utilizzare la propria sessione appiccicosa. Quando si finisce un prodotto e passare al successivo, creare una nuova sessione con un IP diverso.
| Fase | Strategia del proxy | Motivazione |
|---|---|---|
| Ricerca di prodotti | Rotazione per richiesta | Ricerche indipendenti, nessuna sessione necessaria |
| Paginaing recensioni | Sessione appiccicosa per prodotto | Stesso IP attraverso pagine sembra naturale |
| Tra i prodotti | Nuova sessione/IP | Identità fresca per ogni prodotto |
Preparazione dei dati per l'analisi del sentimento
Il testo di revisione raw ha bisogno di preelaborazione prima dell'analisi del sentimento.
import re
from collections import Counter
def clean_review_text(text):
"""Clean review text for analysis."""
# Remove HTML entities
text = re.sub(r'&\w+;', ' ', text)
# Remove excessive whitespace
text = re.sub(r'\s+', ' ', text).strip()
# Remove very short reviews (likely not useful)
if len(text) < 20:
return None
return text
def extract_key_phrases(reviews, min_frequency=3):
"""Extract frequently mentioned phrases from reviews."""
from collections import Counter
import re
words = []
for review in reviews:
if review.text:
# Simple bigram extraction
tokens = re.findall(r'\b\w+\b', review.text.lower())
for i in range(len(tokens) - 1):
bigram = f"{tokens[i]} {tokens[i+1]}"
words.append(bigram)
return Counter(words).most_common(50)
def aggregate_sentiment(reviews):
"""Calculate aggregate sentiment metrics."""
if not reviews:
return {}
ratings = [r.rating for r in reviews if r.rating]
return {
"total_reviews": len(reviews),
"avg_rating": sum(ratings) / len(ratings) if ratings else 0,
"rating_distribution": {
str(i): len([r for r in reviews if r.rating == i])
for i in range(1, 6)
},
"verified_pct": (
len([r for r in reviews if r.verified]) / len(reviews) * 100
if reviews else 0
),
}Scala a milioni di recensioni
Quando la tua lista di destinazione cresce a migliaia di prodotti su più piattaforme, l'architettura conta.
Architettura basata su queue
- Utilizzare una coda di messaggio (Redis, RabbitMQ) per gestire la lista dei prodotti e distribuire il lavoro tra i lavoratori.
- Ogni lavoratore gestisce un prodotto alla volta: impaginare attraverso tutte le recensioni, memorizzare i risultati, passare al prodotto successivo.
- code separate per piattaforma per rispettare i limiti di velocità diversi.
Strategia di stoccaggio
- Conservare l'HTML grezzo nella memorizzazione degli oggetti (S3) per il rielaborazione quando i parser cambiano.
- Conservare le recensioni analizzate in PostgreSQL con la ricerca full-text per l'analisi.
- Utilizzare la deduplica basata su ID recensione o hash per evitare la memorizzazione di duplicati su re-scrapes.
Incremental Scraping
Per il monitoraggio continuo, non è necessario ri-scrape tutte le recensioni ogni volta. Ordina per la più recente e ferma quando hai colpito una recensione che hai già raccolto. Questo riduce drasticamente l'utilizzo del proxy e accelera la raccolta.
Asporto chiave: Ordina le recensioni per i più recenti prima e smettila di raschiare quando hai colpito i contenuti precedentemente raccolti. Questo trasforma un ri-scrape completo in un aggiornamento incrementale.
Migliori Pratiche
- Utilizzare sessioni appiccicose per la paginazione: Mantenere lo stesso IP attraverso pagine di revisione per un singolo prodotto per evitare di attivare il rilevamento anti-bot.
- Limiti di tasso di rispetto: 2-5 secondi ritardi tra le pagine, ritardi più lunghi tra i prodotti. Le diverse piattaforme hanno diverse tolleranze.
- Maniglia pagine vuote: Una pagina di revisione vuota significa che hai raggiunto la fine. Non continuare a provare più pagine.
- Convalida qualità dei dati: Controllare le pagine CAPTCHA, i contenuti vuoti e le recensioni duplicate nel vostro pipeline.
- Uso Prossi residenziali: Essenziale per Amazon e altre piattaforme fortemente protette.
- Conservare in modo incrementale: Elaborare e memorizzare le recensioni mentre li raschiate, non in un lotto alla fine.
Asporto chiave
- I dati di revisione forniscono un'intelligenza competitiva unica che nessun'altra fonte di dati offre.
- Piattaforme diverse richiedono diverse strategie di raschiamento — costruire raschi modulari per piattaforma.
- Utilizzare sessioni appiccicose per la revisione della paginazione e per-richiesta rotazione tra i prodotti.
- Ordina per la prima volta e fermati a recensioni precedentemente raccolte per un efficiente raschiamento incrementale.
- Testo di revisione preprocesso per l'analisi del sentimento: frasi pulite, deduplicate ed estrarre chiave.
- Uso I proxy residenziali di ProxyHat con geo-targeting per un accesso affidabile alle pagine di revisione su tutte le piattaforme.
Pronto per iniziare a raccogliere dati di revisione? Guarda la nostra Guida di raschiamento Amazon per i dettagli specifici della piattaforma e i nostri e-commerce dati scraping guida per la strategia completa. Check usando i proxy in Python e usando i proxy in Node.js per i modelli di implementazione.






