كيفية استخراج مراجعات المنتجات على نطاق واسع باستخدام البروكسيات

تعلّم استعراضات المنتجات من الأمازون ومنابر أخرى على نطاق واسع. Python and Node.js code for multi-platform review collection, pagination handling, and emotional analysis preparation.

كيفية استخراج مراجعات المنتجات على نطاق واسع باستخدام البروكسيات

لمَ (سكراب) يستعرض منتجاته في (سكالي)؟

وتمثل استعراضات المنتجات أحد أهم مصادر البيانات في التجارة الإلكترونية. وهي تكشف عن مشاعر العملاء، وقضايا جودة المنتجات، والطلبات الخاصة، والوضع التنافسي - وهي معلومات لا يمكن أن يوفرها أي مصدر آخر للبيانات. وعلى نطاق الجدول، تتيح بيانات الاستعراض ما يلي:

  • تحليل الاستشعار: تتبع كيف يشعر العملاء حول منتجاتك ومنتجات المنافسين على مر الزمن
  • تنمية المنتجات: (ب) تحديد الشكاوى المتكررة والطلبات المتعلقة بها على نطاق آلاف الاستعراضات.
  • الاستخبارات التنافسية: فهم مواطن القوة المنافسة والضعف من كلمات زبائنهم
  • بحوث السوق: الكشف عن الاحتياجات غير الملباة والاتجاهات الناشئة عن طريق تحليل أنماط الاستعراض عبر الفئات.
  • رصد الجودة: Detect product quality issues early by monitoring review sentiment trends.

The challenge is that review data is spread across multiple platforms (Amazon, Walmart, Best Buy, Trustpilot, Google), each with different structures and anti-bot protections. وتتطلب عمليات استعراض البرمجيات على نطاق واسع استراتيجيات خاصة بالمنبر وبنية أساسية متينة. لأنماط التجارة الإلكترونية الأساسية، نرى دليل جرد بيانات التجارة الإلكترونية.

استعراض هيكل البيانات عبر المنهاج

استعراض هيكل البيانات عبر المنهاج
منهاج العملمجالات الاستعراضالهجراتAnti-Bot Level
Amazonالتصديق، العنوان، النص، التاريخ، التحقق، الأصوات المفيدةالقائمة على الصفحة (10/صفحة)عالية
WalmartRating, title, text, date, submission sourceAPI القائمة على أساس عرضيمتوسطة
أفضل شراءRating, title, text, date, help/unhelpfulAPI القائمة على الصفحةمتوسطة
TrustpilotRating, title, text, date, replyالصفحةLow-Medium
Google ShoppingRating, text, date, sourceمبنية على التموينعالية

Proxy Configuration for Review Scraping

ويشتمل استعراض الخردة على الملاحة المهددة، مما يعني الإبقاء على الجلسات عبر طلبات متعددة. جلسات (بروكس هات) اللزجة مثالية لهذا النمط

ProxyHat Setup

# 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:8080

وللاستعراض للخردة، يرجى استخدام الجلسات اللزجة عند تمهيد جميع الاستعراضات لمنتج واحد، والتناوب في كل طلب عند الانتقال بين منتجات مختلفة. هذا يُذكّرُ سلوكَ التصفيقِ الطبيعيِ عندما a مستعمل يَقْرأُ صفحاتَ متعددةَ مِنْ الاستعراضاتِ لمنتج واحد قبل الإنتقال إلى القادمِ.

Python Implementation

هنا مُخدّرات مُعدّدة تُستخدم (بروكسي هات) (بايتون).

Amazon Review Scraper

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 None

Multi-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 Implementation

A Node.js review scraper using العميل (س.د.ك).

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));
});

معالجة المحركات في سكال

ويمثل تمهيد الاستعراض أحد أكبر التحديات في عملية الخردة على نطاق واسع.

Amazon Pagination Strategy

وتُحدِّد الأمازون صفحات الاستعراض إلى 10 استعراضات لكل منها، وتظهر عادة ما يصل إلى 500 صفحة (خمسة آلاف استعراض). فيما يتعلق بالمنتجات ذات الاستعراضات الإضافية، استخدام بارامترات التصفية للجزء:

# 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 product

إدارة الدورة

استعراض كل منتج يجب أن يستخدم دورته اللزجة عندما تنهي منتجاً واحداً وتنتقل إلى التالي، تخلق جلسة جديدة مع آي بي.

إدارة الدورة
المرحلةالاستراتيجية البديلةالسبب
البحث عن المنتجاتالتناوب حسب الطلبالبحث المستقل، لا حاجة لعقد أي دورة
استعراضات مبدئيةالدورة المرضية لكل منتجنفس IP عبر الصفحات يبدو طبيعيا
بين المنتجاتالدورة الجديدة/البرنامج المتكاملالهوية الجديدة لكل منتج

إعداد بيانات لتحليل الاستشعار

ويحتاج نص استعراض الراو إلى المعالجة المسبقة قبل تحليل المشاعر.

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
        ),
    }

الارتفاع إلى ملايين الاستعراضات

عندما تنمو قائمتك المستهدفة إلى الآلاف من المنتجات عبر المنصات المتعددة، أمور الهندسة

بنية هيكلية ذات أساس كوي

  • Use a message queue (Redis, RabbitMQ) to manage the product list and distribute work across workers.
  • ويتعامل كل عامل مع منتج واحد في وقت واحد: يمهّد من خلال جميع الاستعراضات، ونتائج المخزن، وينتقل إلى المنتج التالي.
  • (ب) الاستفسارات المنفصلة لكل منبر لاحترام حدود مختلفة للمعدلات.

استراتيجية التخزين

  • تخزين خام HTML في تخزين الجسم (S3) لإعادة المعالجة عندما تتغير الطرود.
  • Store parsed reviews in PostgreSQL with full-text search for analysis.
  • Use deduplication based on review ID or hash to avoid storing duplicates on re-scrapes.

التسلل

بالنسبة للرصد المستمر، لا تحتاج إلى إعادة تشكيل جميع الاستعراضات في كل مرة. نوعاً ما في آخر مرة وتوقفي عندما قمتِ بإجراء مراجعة قمتِ بجمعها وهذا يقلل بشكل كبير من الاستخدام المحترف ويسرع في التحصيل.

الوجبات الرئيسية: الاستعراضات العذبة من قبل الأحدث أولاً وتوقف عن الخردة عندما كنت قد حصلت على المحتوى من قبل. هذا يُحوّلُ إعادةً كاملةً إلى تحديث تدريجي.

أفضل الممارسات

  • استخدام الجلسات اللزجة للتمهيد: الحفاظ على نفس IP عبر صفحات الاستعراض بالنسبة لمنتج واحد لتجنب تحريك كشف مضاد للمركبات.
  • حدود معدلات الاحترام: التأخيرات الثانية بين الصفحات، والتأخيرات الأطول بين المنتجات. مختلف البرامج لها تسامحات مختلفة
  • صفحات فارغة اليد: صفحة مراجعة فارغة تعني أنك وصلت للنهاية لا تستمر في محاولة المزيد من الصفحات.
  • تقييم جودة البيانات: تحقق من صفحات CAPTCHA، المحتوى الفارغ، وازدواجية الاستعراضات في خطك.
  • الاستخدام مؤسسات الرعاية: Essential for Amazon and other heavily protected platforms.
  • بشكل تدريجي: عملية ومخزن الاستعراضات عندما تخدشها، ليس في دفعة واحدة في النهاية.

المداخل الرئيسية

  • وتوفر البيانات الاستعراضية معلومات استخبارية تنافسية فريدة لا يعرضها أي مصدر آخر للبيانات.
  • وتتطلب برامج مختلفة استراتيجيات مختلفة للخردة - بناء الخردة النموذجية لكل منصة.
  • Use sticky sessions for review pagination and per-request rotation between products.
  • وتوقف في الاستعراضات التي سبق جمعها من أجل الخردة الإضافية الفعالة.
  • Preprocess review text for emotional analysis: clean, deduplicate, and extract key words.
  • الاستخدام وكيلات النيابة السكنية مع وضع أهداف جغرافية من أجل الوصول الموثوق به إلى صفحات الاستعراض في جميع المنابر.

مستعد لبدء جمع بيانات الاستعراض؟ شاهدْنا دليل خردة الأمازون للتفاصيل الخاصة بالمنبر وتفاصيلنا دليل جرد بيانات التجارة الإلكترونية من أجل الاستراتيجية الكاملة تحقق (بإستعمال المحترفين في (بيثون و (بإستعمال المحترفين في (نودج لأنماط التنفيذ.

¿Listo para empezar?

Accede a más de 50M de IPs residenciales en más de 148 países con filtrado impulsado por IA.

Ver preciosProxies residenciales
← Volver al Blog