Pourquoi faire des critiques de produits à l'échelle?
Les revues de produits sont l'une des sources de données les plus précieuses dans le commerce électronique. Ils révèlent le sentiment de la clientèle, les problèmes de qualité du produit, les demandes de fonctionnalités et le positionnement concurrentiel — informations qu'aucune autre source de données ne peut fournir. À l'échelle, les données d'examen permettent :
- Analyse des sentiments : Suivez la façon dont les clients se sentent au fil du temps à l'égard de vos produits et produits concurrents.
- Développement de produits: Recenser les plaintes récurrentes et les demandes de fonctionnalités dans des milliers d'examens.
- Intelligence compétitive: Comprendre les forces et les faiblesses des concurrents à partir des propres mots de leurs clients.
- Etude de marché: Découvrez les besoins non satisfaits et les tendances émergentes en analysant les modèles d'examen selon les catégories.
- Surveillance de la qualité: Détecter rapidement les problèmes de qualité des produits en surveillant les tendances des sentiments.
Le défi est que les données d'examen sont réparties sur plusieurs plateformes (Amazon, Walmart, Best Buy, Trustpilot, Google), chacune avec des structures différentes et des protections anti-bots. Les examens à grande échelle nécessitent des stratégies spécifiques à la plate-forme et une solide infrastructure de remplacement. Pour les modèles fondamentaux de grattage du commerce électronique, voir notre Guide de suppression des données sur le commerce électronique.
Examiner la structure des données entre les plateformes
| Plateforme | Domaines d'examen | Pagination | Niveau anti-bot |
|---|---|---|---|
| Amazonie | Note, titre, texte, date, vérification, votes utiles | Page (10/page) | Élevé |
| Walmart | Note, titre, texte, date, source de la soumission | API basée sur offset | Moyenne |
| Meilleur achat | Note, titre, texte, date, utile/inutile | API basée sur la page | Moyenne |
| Pilote de confiance | Note, titre, texte, date, réponse | Page-basée | Faible-moyenne |
| Google Shopping | Note, texte, date, source | Base de défilement | Élevé |
Configuration de proxy pour l'examen du scraping
L'examen de la mise au rebut implique une navigation paginée, ce qui signifie la tenue de séances sur plusieurs demandes. Les séances collantes de ProxyHat sont idéales pour ce modèle.
Configuration 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:8080Pour examiner le grattage, utilisez des séances collantes lors de la pagination à travers tous les examens pour un seul produit, et rotation par demande lors du déplacement entre différents produits. Ceci imite le comportement de navigation naturel où un utilisateur lit plusieurs pages de critiques pour un produit avant de passer à la suivante.
Mise en œuvre de Python
Voici un grattoir de revue multi-plateforme utilisant Python SDK de ProxyHat.
Grattoir Amazon Review
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 NoneCollector Multi-Platform Review
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)}")Mise en œuvre de Node.js
A Node.js examen racleur en utilisant Le nœud SDK de 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));
});Manipulation de la pagination à l'échelle
La pagination de l'examen est l'un des plus grands défis de la mise au rebut de l'examen à grande échelle.
Stratégie de pagination de l'Amazone
Amazon limite les pages de révision à 10 revues chacune et affiche généralement jusqu'à 500 pages (5 000 revues). Pour les produits avec plus de commentaires, utilisez les paramètres de filtre pour segmenter :
# 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 productGestion des séances pour Pagination
La pagination d'examen de chaque produit devrait utiliser sa propre session collante. Lorsque vous terminez un produit et passez à l'autre, créez une nouvelle session avec une IP différente.
| Phase | Stratégie de proxy | Motifs |
|---|---|---|
| Trouver des produits | Rotation par demande | Recherches indépendantes, aucune session nécessaire |
| Pagination des revues | Session collante par produit | Même IP sur les pages semble naturel |
| Entre produits | Nouvelle session/IP | Identité fraîche pour chaque produit |
Préparation des données pour l'analyse du sentiment
Le texte d'examen brut a besoin d'un prétraitement avant l'analyse du sentiment.
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
),
}Élargissement à des millions de critiques
Lorsque votre liste cible atteint des milliers de produits sur plusieurs plateformes, l'architecture compte.
Architecture en file d'attente
- Utilisez une file d'attente de message (Redis, RabbitMQ) pour gérer la liste de produits et distribuer le travail à tous les travailleurs.
- Chaque travailleur manipule un produit à la fois : paginer à travers toutes les critiques, stocker les résultats, passer au produit suivant.
- Des files d'attente séparées par plate-forme pour respecter différentes limites de taux.
Stratégie de stockage
- Stocker le HTML brut dans le stockage d'objets (S3) pour le retraitement lorsque les analyseurs changent.
- Conservez les avis analysés dans PostgreSQLTM avec recherche en texte intégral pour l'analyse.
- Utilisez la duplication basée sur l'ID de révision ou le hachage pour éviter de stocker des duplicatas sur des re-crapes.
Dégraissage progressif
Pour une surveillance continue, vous n'avez pas besoin de re-scrape tous les examens à chaque fois. Trier par le plus récent et arrêter lorsque vous avez frappé une revue que vous avez déjà collecté. Cela réduit considérablement l'utilisation des procurations et accélère la collecte.
Key takeaway: Trier les avis par les plus récents d'abord et arrêtez de gratter lorsque vous appuyez sur le contenu précédemment collecté. Cela transforme un re-scrape complet en une mise à jour incrémentale.
Meilleures pratiques
- Utilisez des séances collantes pour la pagination: Maintenir la même IP sur toutes les pages d'examen pour un seul produit pour éviter de déclencher la détection anti-bot.
- Respecter les limites de taux : 2-5 secondes de retard entre les pages, plus de retard entre les produits. Différentes plateformes ont des tolérances différentes.
- Poignez les pages vides : Une page de revue vide signifie que vous avez atteint la fin. N'essayez pas plus de pages.
- Valider la qualité des données : Vérifiez les pages CAPTCHA, le contenu vide et les commentaires en double dans votre pipeline.
- Utilisation Proxies résidentielles: Essentiel pour Amazon et d'autres plateformes fortement protégées.
- Conserver progressivement & #160;: Traitez et entreposez les commentaires pendant que vous les grattez, pas dans un lot à la fin.
A emporter des clés
- Les données d'examen fournissent une intelligence concurrentielle unique qu'aucune autre source de données n'offre.
- Différentes plates-formes nécessitent différentes stratégies de raclage — construire des racleurs modulaires par plate-forme.
- Utilisez des séances collantes pour examiner la pagination et la rotation par demande entre les produits.
- Trier par la plus récente première et de s'arrêter à des avis précédemment recueillis pour le grattage différentiel efficace.
- Texte d'examen préalable pour l'analyse des sentiments : propre, doublonné et extrait des phrases clés.
- Utilisation Proxies résidentielles de ProxyHat avec géo-ciblage pour un accès fiable aux pages d'examen sur toutes les plateformes.
Prêt à commencer à recueillir des données d'examen? Voir notre Guide de grattage de l'Amazone pour les détails spécifiques à la plateforme et notre Guide de suppression des données sur le commerce électronique pour la stratégie complète. Vérifier utilisant des proxies dans Python et utilisant des proxies dans Node.js pour les modèles de mise en œuvre.






