استخدام solvethree في برمجية وسيطة للتنزيل في Scrapy

بقلم solvethreeمدة القراءة: 4 دقيقة

استخدم برمجية وسيطة غير متزامنة للتنزيلات لحل الطلبات التي يضع عليها العنكبوت علامة صريحة فقط. شغّل SDK المتزامن من solvethree في خيط عامل، ثم أعد FormRequest يحتوي على الرمز والوكيل وهوية المتصفح المُعادة.

يتعامل المثال مع نقطة نهاية واحدة مضبوطة مسبقًا لنموذج reCAPTCHA Enterprise. ولا يكتشف التحديات أو كيفية توقّع أي موقع عشوائي استلام رمزه.

في هذه الصفحة

اضبط الوجهة المستهدفة قبل تفعيل البرمجية الوسيطة

  • استخدم Scrapy 2.19+ وPython 3.10+ وSDK الرسمي لـ solvethree بلغة Python. هذا SDK متزامن؛ وليس لديه عميل غير متزامن أصلي.
  • أنشئ ملف تعريف موقع نشطًا لمساحة عملك في لوحة التحكم. إرسال اسم مضيف وإجراء لا ينشئ هذا الملف. راجع إعداد ملف تعريف الموقع.
  • اضبط TARGET_URL على عنوان URL الدقيق لإرسال النموذج، وSOLVETHREE_PROXY على الوكيل المستخدم لطلب التطبيق هذا، وSOLVETHREE_API_KEY على مفتاح مساحة عملك. احتفظ بالمفتاح على جانب الخادم.
  • فعّل AsyncioSelectorReactor وسجّل البرمجية الوسيطة بالأولوية 740، كما هو موضح أدناه. يضعها ذلك قبل HttpProxyMiddleware ذي الأولوية 750.

حلّ الطلبات المعلَّمة صراحةً فقط

Scrapy · حل طلبات النماذج المعلّمة صراحةً فقط
# middlewares.py; Scrapy 2.19+, Python 3.10+, official solvethree SDK.
import asyncio
import os
from urllib.parse import urlsplit
from scrapy.http import FormRequest
from solvethree import Solvethree

class CaptchaMiddleware:
    async def process_request(self, request):
        if not request.meta.get("solvethree_form") or request.meta.get("solvethree_applied"):
            return None
        target = os.environ["TARGET_URL"]
        if request.url != target:
            raise ValueError("Only the configured form target may use this middleware")
        proxy = os.environ["SOLVETHREE_PROXY"]
        def solve():
            return Solvethree(os.environ["SOLVETHREE_API_KEY"]).solve({
                "site": urlsplit(target).hostname, "action": "login", "proxy": proxy,
                "requestId": request.meta["solvethree_request_id"],
            }, timeout=180)
        result = await asyncio.to_thread(solve)
        solution = result["solution"]
        fields = dict(request.meta["solvethree_fields"])
        fields["g-recaptcha-response"] = solution["token"]
        meta = {**request.meta, "proxy": proxy, "solvethree_applied": True,
                "dont_retry": True, "dont_redirect": True}
        return FormRequest(target, formdata=fields, callback=request.callback,
            errback=request.errback, headers={"User-Agent": solution["userAgent"],
                "sec-ch-ua": solution["secChUa"]}, meta=meta, dont_filter=True)

# settings.py:
# TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
# DOWNLOADER_MIDDLEWARES = {"myproject.middlewares.CaptchaMiddleware": 740}
# The spider first loads its form/CSRF data with the same proxy and cookiejar.
# Then yield a Request(TARGET_URL, callback=your_result_handler, meta={
#     "solvethree_form": True, "solvethree_request_id": one_saved_logical_job_id,
#     "solvethree_fields": {"csrf": token_from_the_form, "email": "your-test-value"},
#     "cookiejar": your_cookiejar_id,
# })
# Inspect the final response in your_result_handler; a ready task is not that response.

تأخذ الدالة process_request في البرمجية الوسيطة الوسيط request فقط، دون الوسيط spider المُهمَل. تمر الطلبات غير المعلَّمة دون تغيير. يجب أن يطابق الطلب المعلَّم TARGET_URL تمامًا؛ ويؤدي عدم التطابق إلى طرح خطأ بدلًا من إرسال رمز إلى نقطة نهاية أخرى.

يبقي asyncio.to_thread استدعاءات الشبكة والاستعلام الدوري الخاصة بـ SDK المتزامن خارج خيط حلقة الأحداث. مجرد تعريف process_request على أنها async لا يحقق ذلك. ينشئ SDK مهمة وينتظر نتيجة جاهزة أو يطرح استثناءً؛ ثم تبني البرمجية الوسيطة طلب إرسال النموذج.

طابق النموذج الذي يرسله تطبيقك فعليًا

  1. 1.

    اضبط الإجراء وحقل الرمز الصحيحين

    يستخدم المثال الإجراء login ويضع solution.token في g-recaptcha-response. غيّرهما ليتطابقا مع تكامل الوجهة المستهدفة. تُشتق قيمة site للمهمة من اسم المضيف في TARGET_URL؛ ولا تقبل مهام reCAPTCHA حقلَي type أو url. يؤدي إغفال recaptchaType إلى اختيار enterprise-v3.

  2. 2.

    وفّر حقول النموذج الموجودة

    يجب أن يملأ العنكبوت solvethree_fields بالحقول المطلوبة لنقطة النهاية، بما فيها قيمة CSRF الحالية. تنسخ البرمجية الوسيطة تلك الحقول وتضيف الرمز؛ ولا تحمّل النموذج أو تستخرج حقول الإدخال المخفية.

  3. 3.

    حافظ على اتساق الجلسة

    حمّل النموذج الأولي عبر الوكيل نفسه وهوية المتصفح نفسها اللذين يتطلبهما التطبيق. مرّر معرّف cookiejar الخاص به في البيانات الوصفية للطلب المعلَّم. يحتفظ FormRequest المُعاد بـ cookiejar نفسه ويستخدم solution.userAgent وsolution.secChUa، لكن المثال لا يجهّز الجلسة السابقة أو يصلحها.

  4. 4.

    تعامل مع استجابة التطبيق

    وفّر دالة callback تتحقق من نجاح إرسال النموذج، ودالة errback لحالات فشل الطلب. تعني جاهزية المهمة أنه تم إنشاء حل، لا أن الموقع قبل الطلب اللاحق.

يستخدم هذا المثال عمدًا وكيلًا واحدًا للحل والإرسال. لا تستبدله بوكيل غير مرتبط بعد الحل. وافحص أيضًا أي برمجية وسيطة مخصصة للتنزيلات تعيد كتابة User-Agent أو تلميحات العميل: يجب ألا تستبدل الهوية المُعادة مع الحل.

امنع إعادة المحاولة من إنشاء محاولة حل أخرى

احفظ solvethree_request_id قبل تمرير الطلب المعلَّم باستخدام yield، واحتفظ به لمحاولة الحل المنطقية نفسها. يقبل requestId من 1–64 حرفًا أو رقمًا أو شرطة سفلية أو شرطة من مجموعة ASCII. تؤدي إعادة استخدامه مع مدخلات مهمة مطابقة إلى استعادة المهمة الموجودة؛ أما تغيير تلك المدخلات مع الاحتفاظ بالمعرّف فيؤدي إلى تعارض.

يضبط FormRequest المُعاد solvethree_applied كي لا يؤدي إلى محاولة حل أخرى. ويضبط أيضًا dont_retry وdont_redirect، لمنع إعادة المحاولة وإعادة التوجيه تلقائيًا لهذا الإرسال. لا تمنع هذه العلامات دالة callback أو مشغّل المهام الخاص بك من بدء طلب آخر، لذا اتخذ هذا القرار صراحةً.

تنتهي مهلة استدعاء الحل.

تحقق مما إذا كانت قد أُنشئت مهمة بالفعل. انتهاء مهلة الاتصال لا يثبت فشل الإنشاء.

جرّب هذا: استرجع المهمة المعروفة أو استعدها باستخدام requestId المحفوظ ومدخلات المهمة المطابقة قبل إنشاء طلب حل منطقي جديد.

تُطلق عملية الحل استثناءً بدلًا من إرجاع نتيجة.

ميّز بين خطأ في طلب HTTP وفشل نهائي للمهمة. عند فشل المهمة، افحص errorCode وerror.

جرّب هذا: عالج الفشل بدلًا من إعادة تمرير الطلب المعلَّم نفسه مرارًا. صحّح المدخلات غير الصالحة قبل المحاولة مجددًا؛ يجب إيقاف الاستطلاع للمهام الفاشلة.

يرفض الموقع النموذج المُرسَل.

افحص أولًا حقل الرمز الصادر وحقول CSRF وملفات تعريف الارتباط والوكيل وهوية المتصفح.

جرّب هذا: صحّح طلب التطبيق قبل الدفع مقابل حل آخر. يجب أن يحتوي الحقل على solution.token، لا معرّف المهمة أو رمز قديم.

شغّل مهمتك الأولى.

ابدأ برصيد قدره $5 في مساحة العمل.

إنشاء مساحة عمل
استخدام solvethree في برمجية وسيطة للتنزيل في Scrapy · solvethree