إعداد بروكسي Scrapy، استخدام IP مختلف لكل طلب عبر meta proxy
يشرح هذا الدليل كيفية توصيل بروكسي HTTP من Socks5Proxy في Scrapy باستخدام meta proxy، وبرنامج وسيط لتحميل القوائم المستلمة من API وتناوبها لكل طلب، وإعدادات السرعة المناسبة للموقع الهدف.
كيف يعالج Scrapy البروكسي؟
يتم تفعيل HttpProxyMiddleware افتراضيًا في Scrapy. بإدخال العنوان في مفتاح proxy في قاموس meta للطلب، سيتم إرسال ذلك الطلب عبر البروكسي المحدد، وسيتم تحويل اسم المستخدم وكلمة المرور في العنوان إلى رأس Proxy-Authorization من قبل middleware. تمر عناوين HTTPS عبر نفق CONNECT.
معالج التنزيل الافتراضي في Scrapy يدعم بروكسي HTTP. إذا كنت بحاجة ماسة إلى SOCKS5، فستحتاج إلى معالج منفصل، لذا يوصى باستخدام منفذ HTTP لنفس IP في Scrapy. سيرى الموقع المستهدف نفس IP.
يستخدم المثال عنوان IP 198.51.100.23 ومنفذ HTTP 8000 واسم المستخدم spx_user وكلمة المرور spx_pass.
pip install scrapy
scrapy startproject shop
cd shopكيفية إضافة بروكسي إلى طلب واحد؟
أضف proxy إلى meta عند إنشاء Request في start_requests. كرر نفس الأسلوب عند طلب الصفحة التالية في رد الاتصال. للحفاظ على نفس الجلسة، انقل قيمة proxy من meta الاستجابة السابقة للحفاظ على نفس IP.
import scrapy
PROXY = "http://spx_user:spx_pass@198.51.100.23:8000"
class IpCheckSpider(scrapy.Spider):
name = "ip_check"
def start_requests(self):
yield scrapy.Request("https://api.ipify.org?format=json", meta={"proxy": PROXY})
def parse(self, response):
self.logger.info("seen as %s", response.json()["ip"])كيفية تناوب IPs لكل طلب؟
يمكنك إنشاء وسيط تنزيل لإضافة البروكسي التالي إلى كل طلب دون الحاجة إلى تغيير كود العنكبوت. الوسيط التالي يحصل على القائمة من API عند البدء، وإذا كان meta يحتوي بالفعل على proxy، فإنه يتركه كما هو للسماح باستخدام الجلسة الثابتة والدوران معًا.
ضع مفتاح API في settings.py أو اقرأه من متغيرات البيئة. يجب تسجيله برقم أقل من HttpProxyMiddleware الأساسي (750) حتى تتمكن البرمجية الوسيطة من معالجة العناوين التي تدخلها البرمجية الوسيطة الأساسية.
import itertools
import requests
class RotatingProxyMiddleware:
def __init__(self, key):
text = requests.get(
"https://socks5proxy.io/api/v1/proxies/download",
params={"format": "user:pass@ip:port", "protocol": "http"},
headers={"Authorization": "Bearer " + key},
timeout=30,
).text
self.pool = itertools.cycle(["http://" + l.strip() for l in text.splitlines() if l.strip()])
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings.get("SPX_API_KEY"))
def process_request(self, request, spider):
if "proxy" not in request.meta: # keep a proxy that was set on purpose (sticky sessions)
request.meta["proxy"] = next(self.pool)SPX_API_KEY = "YOUR_API_KEY"
DOWNLOADER_MIDDLEWARES = {
"shop.middlewares.RotatingProxyMiddleware": 740,
}
CONCURRENT_REQUESTS = 32
CONCURRENT_REQUESTS_PER_DOMAIN = 16
DOWNLOAD_DELAY = 0.25
AUTOTHROTTLE_ENABLED = True
RETRY_TIMES = 3
RETRY_HTTP_CODES = [429, 500, 502, 503, 504, 522, 524, 408]
DOWNLOAD_TIMEOUT = 30كيف يتم ضبط السرعة وإعادة المحاولة؟
CONCURRENT_REQUESTS_PER_DOMAIN هو عدد الطلبات التي يمكن إرسالها إلى نفس النطاق في نفس الوقت. كلما زاد عدد IPs الوكيل، يمكنك زيادة هذه القيمة دون زيادة العبء على IP واحد. على سبيل المثال، إذا كنت ترسل 50 طلبًا متزامنًا باستخدام 500 IP، فإن IP واحدًا يستخدم في المتوسط مرة واحدة كل 10 طلبات.
عند تفعيل AUTOTHROTTLE، يتم تعديل الفاصل الزمني للطلبات تلقائيًا حسب سرعة الاستجابة. إذا زادت استجابات 429، يمكنك إعادة المحاولة باستخدام RETRY_HTTP_CODES، ولكن يمكنك أيضًا مسح proxy في meta لإدخال الوكيل التالي عند إعادة المحاولة.
إضافة خطوة في خط الأنابيب للتحقق من أن النتائج المجمعة هي صفحات فعلية وليست شاشات تأكيد يحسن جودة البيانات. يمكنك جعل النظام يعيد إرسال الطلب باستخدام عنوان IP آخر إذا كانت الاستجابة لا تحتوي على العناصر المطلوبة.
- ضبط عدد الطلبات المتزامنة لكل نطاق بناءً على عدد IPs
- AUTOTHROTTLE لتعديل الفاصل الزمني حسب سرعة الاستجابة
- 429 و 5xx: حاول مرة أخرى مع IP آخر
- تصفية صفحات التحقق بفحص محتوى الاستجابة
ما الذي يتغير عند الاتصال باستخدام تفويض IP؟
قم بتسجيل IPv4 لخادم Scrapy في لوحة التحكم، ثم يمكنك استخدام meta proxy مثل http://198.51.100.23:8000 بدون اسم مستخدم وكلمة مرور. يمكنك أيضًا استلام القائمة بتنسيق format=ip:port. إذا كنت تقوم بتشغيل العناكب على عدة خوادم، قم بتسجيل جميع عناوين IP الخاصة بها. يمكنك تسجيل حتى 10 عناوين IP كحد أقصى.
كيفية ربط الطلبات التي تتطلب جلسة بنفس IP؟
لعمليات مثل تسجيل الدخول أو عربة التسوق حيث يجب استمرار الكوكيز، استخدم نفس الIP. أضف الوكيل مباشرة في الطلب الأول، ثم في رد الاتصال، استخدم نفس قيمة الوكيل من response.meta للطلبات التالية حتى لا يغيرها البرنامج الوسيط. باستخدام مفتاح cookiejar في Scrapy، يتم فصل الكوكيز لكل جلسة.
إذا قمت بإقران بروكسي واحد مع مجموعة ملفات تعريف الارتباط في كل جلسة، يمكنك تشغيل عدة جلسات في وقت واحد دون أن تختلط مع بعضها البعض.
import scrapy
PROXIES = [
"http://spx_user:spx_pass@198.51.100.23:8000",
"http://spx_user:spx_pass@198.51.100.24:8000",
]
class SessionSpider(scrapy.Spider):
name = "sessions"
def start_requests(self):
for i, proxy in enumerate(PROXIES):
yield scrapy.Request("https://example.com/", meta={"proxy": proxy, "cookiejar": i}, dont_filter=True)
def parse(self, response):
# follow-up request keeps the same proxy and the same cookie jar
yield response.follow("/account", meta={"proxy": response.meta["proxy"], "cookiejar": response.meta["cookiejar"]}, callback=self.parse_account)
def parse_account(self, response):
self.logger.info("status %s via %s", response.status, response.meta["proxy"])كيف يمكنني إزالة بروكسي فاشل مؤقتًا؟
إذا تلقيت استجابة 403 أو 429 في process_response للبروكسي، يمكنك إعطاء البروكسي استراحة لبضع دقائق وإعادة إرسال الطلب إلى بروكسي آخر. قم بنسخ الطلب، وإزالة البروكسي من meta، وتشغيل dont_filter، ثم إعادته حتى يدخل البروكسي التالي.
يمكنك إدارة قائمة عناوين IP المستريحة ووقت إعادة استخدامها بسهولة باستخدام قاموس. تجنب استخدام نفس العنوان IP فورًا لمنح موقع الهدف وقتًا لرفع القيود.
ما الذي يجب ضبطه في Scrapy لتوفير النطاق الترددي؟
Scrapy يستقبل HTML فقط افتراضيًا ويستخدم نطاق ترددي أقل بكثير من أدوات المتصفح. مع HttpCompressionMiddleware المفعّل افتراضيًا لاستقبال الردود المضغوطة، ينخفض حجم النقل أكثر. هذا هو السبب في إمكانية جمع العديد من الصفحات ضمن النطاق الترددي الشهري للخطة المشتركة.
لتجنب استلام نفس الصفحة مرارًا، قم بتمكين HTTPCACHE_ENABLED أثناء التطوير لتجنب إعادة تحميل الموقع والوكيل في كل اختبار. في التشغيل، حافظ على تصفية العناوين المكررة واستخدم dont_filter فقط للطلبات التي تحتاج إعادة تحميل.
من المهم أيضًا تضييق نطاق الروابط المتابعة لمنع الانتشار إلى صفحات فرعية غير ضرورية. بتحديد نطاق الجمع بوضوح، يتم تقليل الوقت والنطاق الترددي وعبء الموقع المستهدف.
كيف يتم حل المشكلات الشائعة؟
إذا ظهرت استجابة 407، تحقق من اسم المستخدم وكلمة المرور في العنوان. إذا كانت كلمة المرور تحتوي على أحرف خاصة، يجب ترميزها بنسبة مئوية. TunnelError يعني أن الوكيل لم يتلق طلب CONNECT، تأكد من أن المنفذ هو منفذ HTTP.
إذا كانت جميع الطلبات تخرج من نفس عنوان IP، فإما أن يكون ترتيب middleware بعد HttpProxyMiddleware، أو أن spider يقوم بإضافة meta proxy مباشرة. تحقق من ترتيب settings.py وكود spider.