

در این مقاله قدمبهقدم میفهمیم چگونه با Scrapy یک اسپایدر بسازیم که «نظرات محصول» در Amazon را اسکریپ کند. هدف این راهنما تولید خروجی قابل استفاده (CSV/DB)، عبور از صفحات نظرات (pagination)، مدیریت بلاک و مانیتورینگ است. در پایانِ این مقاله شما: 1) ساختار یک اسپایدر برای پیدا کردن صفحه محصول و استخراج نظرات را میدانید، 2) روش ذخیرهسازی داده و پیکربندی FEEDS را بلدید، و 3) با روشهای معمول عبور از محافظتهای ضدبات آشنا میشوید.
چالش اصلی در اسکریپ کردن نظرات Amazon این است که دسترسی مستقیم به مسیر «product-reviews» معمولاً به ریدایرکت لاگین یا صفحات محافظتشده منجر میشود. راه حل پایدارتر این است که ابتدا از صفحهٔ جستجو (search) برای پیدا کردن آدرس واقعی محصول استفاده کنیم و سپس صفحهٔ نظرات آن محصول را دنبال کنیم. این روش باعث میشود آدرس صحیح محصول را گرفته و ریدایرکتهای محافظتی را دور بزنیم.
ورودی اصلی اسپایدر، فهرستی از ASIN است. به ازای هر ASIN ابتدا یک درخواست به صفحهٔ جستجو میفرستیم تا لینک محصول در نتایج را استخراج کنیم. سپس با آن لینک به صفحهٔ نظرات میرویم.
import scrapy
from urllib.parse import urljoin
class AmazonReviewsSpider(scrapy.Spider):
name = 'amazon_reviews'
def start_requests(self):
# ورودی: لیست ASINها
asin_list = ['B09G9FPHY6']
AMAZON_BASE = 'AMAZON_BASE_URL' # مقدار واقعی را در پروژه قرار دهید
for asin in asin_list:
# ساخت URL جستجو؛ این رشتهها نمونه هستند و باید با دامنه واقعی جایگزین شوند
search_url = f"{AMAZON_BASE}/s?k={asin}"
yield scrapy.Request(url=search_url,
callback=self.discover_product_urls,
meta={'asin': asin, 'page': 1})
def discover_product_urls(self, response):
# ورودی: response صفحهٔ نتایج جستجو
# خروجی: درخواست به صفحهٔ محصول (که به parse_reviews متصل است)
asin = response.meta['asin']
# انتخاب نتایج جستجو؛ سلکتورها ممکن است بسته به قالب صفحه تغییر کنند
search_products = response.css('div.s-result-item[data-component-type=s-search-result]')
for product in search_products:
relative_url = product.css('a::attr(href)').get()
if not relative_url:
continue
product_url = urljoin('AMAZON_BASE_URL', relative_url).split('?')[0]
yield scrapy.Request(url=product_url,
callback=self.parse_reviews,
meta={'asin': asin, 'retry_count': 0})
def parse_reviews(self, response):
# ورودی: response صفحهٔ محصول یا صفحهٔ نظرات
# خروجی: آیتمهای دیکشنری هر نظر
asin = response.meta.get('asin')
# انتخاب عناصر نظر؛ سلکتورها را براساس HTML واقعی صفحه تطبیق دهید
review_elements = response.css('li[data-hook="review"]')
for review_element in review_elements:
product_data = {
'asin': asin,
'text': ''.join(review_element.css('span[data-hook=review-body] ::text').getall()).strip(),
'title': review_element.css('*[data-hook=review-title]>span::text').get(),
'location_and_date': review_element.css('span[data-hook=review-date] ::text').get(),
'verified': bool(review_element.css('span[data-hook=avp-badge-linkless] ::text').get()),
'rating': review_element.css('*[data-hook*=review-star-rating] ::text').re_first(r"(\d+\.*\d*)")
}
# نقش هر بخش:
# - asin: ASIN ورودی تا مرجع را نگه داریم
# - text: متن کامل نظر، با حذف فاصلههای اضافی
# - title: عنوان نظر
# - location_and_date: متن تاریخ/مکان
# - verified: بولین برای نشان دادن اینکه خرید تاییدشده است یا خیر
# - rating: نمره عددی استخراجشده از متن
print(product_data) # برای دیباگ؛ در تولیدی میتوانید این را حذف کنید
yield product_data
# مدیریت صفحهبندی: اگر لینک صفحهٔ نظرات بعدی وجود داشت، آن را دنبال کنید
next_page = response.css('ul.a-pagination li.a-last a::attr(href)').get()
if next_page:
next_url = urljoin('AMAZON_BASE_URL', next_page)
yield scrapy.Request(url=next_url, callback=self.parse_reviews, meta={'asin': asin})توضیح مرحلهای کد:
صفحات نظرات معمولاً به صورت صفحهای ارائه میشوند؛ برای پوشش کامل باید لینک «بعدی» را دنبال کنید. اگر API یا پارامترهای جاوااسکریپتی وجود دارد که صفحهبندی را کنترل میکنند، میتوان از rendering با headless browser یا از آن پارامترها استفاده کرد.
برای پایداری بهتر:
با قابلیت Feed Export در Scrapy میتوانید خروجی را مستقیم به فایل CSV، JSON یا به سیستمی مانند S3 ارسال کنید. نمونهٔ پیکربندی ساده:
FEEDS = {
'data/%(name)s_%(time)s.csv': {'format': 'csv'},
}توضیح: این تنظیم هنگام اجرای اسپایدر یک فایل در پوشهٔ data میسازد که نام آن شامل نام اسپایدر و زمان اجراست. برای ارسال به S3 یا دیتابیس باید تنظیمات مخصوص آن سرویس و کلیدها را در پروژه اضافه کنید (در محیطهای تولیدی از متغیرهای محیطی برای نگهداری کلیدهای محرمانه استفاده کنید).
Amazon از مکانیزمهای مختلف برای تشخیص باتها استفاده میکند: نرخ درخواست، کپچا، fingerprint مرورگر و ریدایرکتهای لاگین. چند راهکار عملی:
نمونهٔ دستور آزمایشی برای تست پروکسی (از نامگذاری جایگزین برای URLها استفاده کنید):
curl "PROXY_API_ENDPOINT?api_key=YOUR_API_KEY&url=TARGET_URL"نکته امنیتی: هرگز کلیدهای API را در کد منبع عمومی قرار ندهید؛ از متغیرهای محیطی یا سرویسهای مدیریت اسرار استفاده کنید.
اگر از یک SDK یا middleware آماده استفاده میکنید (مثلاً یک Proxy SDK برای Scrapy)، معمولاً به این شکل آن را در settings.py فعال میکنید:
SCRAPEOPS_API_KEY = 'YOUR_API_KEY'
SCRAPEOPS_PROXY_ENABLED = True
DOWNLOADER_MIDDLEWARES = {
'scrapeops_scrapy_proxy_sdk.scrapeops_scrapy_proxy_sdk.ScrapeOpsScrapyProxySdk': 725,
}برای مانیتورینگ نیز میتوانید یک اکستنشن اضافه کنید تا لاگها و متریکها به داشبورد ارسال شوند:
EXTENSIONS = {
'scrapeops_scrapy.extension.ScrapeOpsMonitor': 500,
}
DOWNLOADER_MIDDLEWARES.update({
'scrapeops_scrapy.middleware.retry.RetryMiddleware': 550,
'scrapy.downloadermiddlewares.retry.RetryMiddleware': None,
})توضیح: با این تنظیمات، منطق retry و پروکسی از SDK استفاده میکند و دادههای مانیتورینگ ارسال میشود. مقداردهی صحیح اولویتها (اعداد) مهم است؛ ترتیب اجرای میدلورها به این مقادیر وابسته است.
برای بهینهسازی عملکرد و کاهش ریسک بن شدن:
برای اجرا در محیط تولید، اسپایدر را روی سرور یا سرویس زمانبندیشده اجرا کنید. راهکارهای معمول:
نکتهی عملی: ابتدا اجرای آزمایشی با حجم کم و مانیتورینگ کامل راهاندازی کنید و سپس تعداد همزمانی و دفعات اجرا را افزایش دهید تا رفتار محافظتهای سایت مشخص شود.
هنگام اسکریپ کردن دادهها به قوانین مالکیت محتوا، شرایط استفاده سایت و حریم خصوصی کاربران توجه کنید. برای دسترسی خودکار در مقیاس بالا بهتر است از API رسمی (در صورت وجود) استفاده کنید یا مجوزهای لازم را کسب کنید.
این راهنما یک مسیر عملی برای اسکریپ کردن نظرات Amazon با Scrapy نشان داد: از استفاده از ASINها و جستجو برای کشف آدرس محصول تا استخراج نظرات، مدیریت صفحهبندی، ذخیرهسازی خروجی و عبور از مکانیزمهای ضدبات. توصیههای کلیدی: سلکتورهای خود را مرتباً تست کنید، از پراکسی و چرخش هدرها استفاده کنید، خروجی را با FEEDS مدیریت کنید و مانیتورینگ برای پایداری تولیدی فراهم کنید. با رعایت این موارد میتوانید یک pipeline قابل اتکا برای اسکریپ کردن نظرات بسازید.

