مقدمه
در اسکریپینگ، فشار زیاد به سرور هدف از طریق ارسال پیدرپی درخواستها میتواند تجربه کاربران واقعی را خراب کند و حتی شبیه یک حمله DDoS شود. در این مقاله عملی مخصوص توسعهدهندگان پایتون، روشهای معتبر و مؤثر برای قرار دادن تأخیر بین درخواستها در Scrapy را توضیح میدهیم. در پایان میآموزید چگونه از DOWNLOAD_DELAY، تأخیرهای تصادفی یا ثابت و افزونه AutoThrottle استفاده کنید و بهترین تنظیمهای عملکرد و پایداری را برقرار کنید.
چرا نباید از time.sleep استفاده کنید
در اسکریپرهای ساده مبتنی بر requests معمولاً توسعهدهندگان از time.sleep برای تأخیر بین درخواستها استفاده میکنند. اما در Scrapy این کار اشتباه است، چون Scrapy از فریمورک همزمانی Twisted استفاده میکند و فراخوانی time.sleep واکنشگر (reactor) را مسدود میکند. نتیجهٔ این کار توقف کامل کانکرنسی، صفبندی نامناسب درخواستها و کاهش شدید کارایی است.
به جای آن باید از تنظیمات داخلی Scrapy یا افزونههای غیرمسدودکننده استفاده کنید تا همزمانی حفظ شود و تأخیرها بهصورت غیربلوککننده اعمال شوند.
تنظیم DOWNLOAD_DELAY
سادهترین روش گذاشتن تأخیر بین درخواستها، تنظیم DOWNLOAD_DELAY در settings.py است. مقدار پیشفرض 0 است که یعنی هیچ تأخیری وجود ندارد؛ با انتخاب مقدار غیرصفر، Scrapy بین درخواستهای ارسالشده به همان دامنه تاخیر اعمال میکند.
# settings.py
DOWNLOAD_DELAY = 2 # 2 ثانیه تأخیر حداقل برای هر دامنههمچنین میتوانید این مقدار را بهصورت محلی برای هر اسپایدر با custom_settings تعیین کنید (مفید وقتی اسپایدرها را با CrawlerProcess اجرا میکنید):
# bookspider.py
import scrapy
class BookSpider(scrapy.Spider):
name = 'bookspider'
start_urls = ['http://books.toscrape.com']
custom_settings = {
'DOWNLOAD_DELAY': 2, # 2 ثانیه
}
def parse(self, response):
# ورودی: response از یک صفحه
# خروجی: آیتمهایی که yield میشوند یا درخواستهای بعدی
for article in response.css('article.product_pod'):
yield {
'url': article.css('h3 > a::attr(href)').get(),
'title': article.css('h3 > a::attr(title)').get(),
'price': article.css('.price_color::text').get(),
}توضیح کوتاه: این اسپایدر با هر پاسخ یک مجموعه آیتم میسازد و شکل کارکرد DOWNLOAD_DELAY تضمین میکند که بین درخواستها برای همان دامنه فاصلهای حداقل وجود داشته باشد.
تأخیرهای تصادفی (Randomize)
بهصورت پیشفرض، Scrapy وقتی DOWNLOAD_DELAY تعیین کرده باشید، مقدار واقعی تأخیر را کمی تصادفی میکند تا الگوی ثابت نشود. این خصلت با تنظیم پیشفرض RANDOMIZE_DOWNLOAD_DELAY = True فعال است و محدودهٔ تأخیر بین 0.5 * DOWNLOAD_DELAY تا 1.5 * DOWNLOAD_DELAY خواهد بود. برای مثال با DOWNLOAD_DELAY = 2 تأخیر واقعی بین حدود 1 تا 3 ثانیه قرار میگیرد.
مزیت: تقلید رفتار انسانی بهتر و کاهش شناسایی توسط سیستمهای دفاعی. معایب: بازده کلی پایینتر و نوسان زمان اجرا.
تأخیر ثابت
اگر خواستید تأخیر دقیق و ثابتی بین درخواستها اعمال شود، RANDOMIZE_DOWNLOAD_DELAY را به False تنظیم کنید:
# settings.py
DOWNLOAD_DELAY = 2
RANDOMIZE_DOWNLOAD_DELAY = False # تأخیر دقیق 2 ثانیه بین درخواستهانکته: تأخیر ثابت باعث میشود رفتار شما قابلپیشبینیتر شود که ممکن است برخی سیستمها را برای شناسایی آسانتر کند؛ معمولاً ترکیب محدودهٔ تصادفی با مقادیر مناسب بهتر است.
استفاده از افزونه AutoThrottle
AutoThrottle افزونهای داخلی در Scrapy است که بهصورت پویا تأخیرها را بر اساس تأخیر پاسخها (latency) و وضعیت پاسخها تنظیم میکند. مزیت بزرگ آن این است که خودش سعی میکند بار روی سرور هدف را کاهش دهد و در مواجهه با خطاها یا تأخیرهای زیاد کندتر عمل کند.
- سازگاری با سایت: بهجای انتخاب دستی یک تأخیر ثابت، AutoThrottle با توجه به سرعت پاسخدهی سرور مقدار مناسب را تنظیم میکند.
- کاهش سرعت هنگام خطا: وقتی پاسخها خطا بازمیگردانند (غیر 2XX)، افزونه تندتر عمل نمیکند بلکه معمولاً کند میشود که مانع فشار بیشتر روی سرور میشود.
الگوریتم AutoThrottle به اختصار
- اسپایدر با مقدار AUTOTHROTTLE_START_DELAY شروع میکند.
- هنگام دریافت پاسخ، تأخیر هدف بهصورت latency / AUTOTHROTTLE_TARGET_CONCURRENCY محاسبه میشود.
- تأخیر واقعی برای درخواستهای بعد میانگین تأخیرهای قبلی و تأخیر هدف میشود (نرمسازی تغییرات).
- پاسخهای غیر 200 باعث کاهش تأخیر نمیشوند (یعنی افزونه محافظهکار است).
- تأخیر نمیتواند از DOWNLOAD_DELAY کمتر یا از AUTOTHROTTLE_MAX_DELAY بیشتر شود.
پیکربندی AutoThrottle
برای فعالسازی کافیست در settings.py یا custom_settings آن را روشن کنید:
# settings.py
DOWNLOAD_DELAY = 2 # حداقل تأخیر
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5.0
AUTOTHROTTLE_MAX_DELAY = 60.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
AUTOTHROTTLE_DEBUG = False # True برای نمایش آمار در زمان اجراشرح پارامترها:
- AUTOTHROTTLE_START_DELAY: مقدار شروعی قبل از یادگیری رفتار سایت (پیشفرض 5.0).
- AUTOTHROTTLE_MAX_DELAY: حداکثر تأخیر مجاز (پیشفرض 60.0).
- AUTOTHROTTLE_TARGET_CONCURRENCY: هدف تعداد درخواستهای همزمان به یک سایت (پیشفرض 1).
- AUTOTHROTTLE_DEBUG: نمایش لاگهای دقیق برای تحلیل تأخیرها.
نمونهٔ عملی: تنظیمات پیشنهادی و توضیح خطبهخط
# settings.py (پیشنهاد برای اسکریپینگ مودبانه)
DOWNLOAD_DELAY = 1.5
RANDOMIZE_DOWNLOAD_DELAY = True
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 2.0
AUTOTHROTTLE_MAX_DELAY = 30.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
CONCURRENT_REQUESTS = 16
CONCURRENT_REQUESTS_PER_DOMAIN = 4
CONCURRENT_REQUESTS_PER_IP = 4
# رعایت robots.txt را نیز در نظر بگیرید
ROBOTSTXT_OBEY = True
# زمانبندی retry و middlewareها را متناسب با نیاز تنظیم کنیدتوضیح کلی:
- DOWNLOAD_DELAY مقدار پایهٔ تأخیر را تعیین میکند.
- RANDOMIZE_DOWNLOAD_DELAY باعث میشود الگو طبیعیتر شود.
- AUTOTHROTTLE شرایط شبکه و سرور را پایش میکند و مطابق آن تأخیر را تغییر میدهد.
- CONCURRENT_REQUESTS_PER_DOMAIN و PER_IP گرفتن کنترل دقیقتر روی همزمانی برای هر دامنه را ممکن میسازد.
نکات عملکرد، پایداری و امنیت
- مسدود شدن و شناسایی: ترکیب تأخیر مناسب، رندومسازی، تنظیم هدرها (مثل User-Agent) و چرخش پراکسیها شانس بلاک شدن را کم میکند.
- I/O و ذخیرهسازی: اگر pipeline شما با I/O کند (مثلاً نوشتن به دیتابیس یا دیسک) همراه است، بهتر است عملیات ذخیرهسازی را آسنکرون یا باتچ کنید تا throughput کلی پایین نیاید.
- مانیتورینگ: فعالسازی AUTOTHROTTLE_DEBUG یا لاگینگ جامع کمک میکند نقاط تنگاوی (latency spikes) را پیدا و رفع کنید.
- خطاها و backoff: استفاده از Retry Middleware با backoff تدریجی همراه با AutoThrottle رفتار مطمئنی ایجاد میکند تا در مواجهه با خطا فشار بیشتر به سرور وارد نشود.
- قانونی و اخلاقی: همیشه قوانین سایت هدف، فایل robots.txt و شرایط استفاده را بررسی کنید. احترام به سرورها و کاربران اولویت دارد.
جمعبندی
بهجای استفاده از time.sleep، از امکانات خود Scrapy بهره ببرید: DOWNLOAD_DELAY و RANDOMIZE_DOWNLOAD_DELAY کنترل سادهای فراهم میکنند و AutoThrottle بهترین گزینه برای تطبیق خودکار با شرایط سرور است. تنظیم درست همزمانی، رندومسازی و مانیتورینگ باعث میشود اسکریپهای شما هم مؤثر و هم مؤدب باشند.





