خانه/مقالات/اسکریپینگ با Scrapy: ورود و مدیریت لاگین
وب اسکریپینگ
سلنیوم
ضد بلاک (Anti-bot)
برگشت به مقاله‌ها

اسکریپینگ با Scrapy: ورود و مدیریت لاگین

اسکریپینگ با Scrapy: ورود و مدیریت لاگین
این مقاله راهنمای عملی ورود به سایت‌ها با Scrapy را پوشش می‌دهد: تحلیل فرایند لاگین، سه روش رایج (FormRequest ساده، استخراج داده‌های پنهان و لاگین با مرورگر headless) همراه با مثال‌های پایتون و نکات ضد بلاک و ملاحظات حقوقی. پس از خواندن، می‌توانید تصمیم بگیرید کدام روش مناسب هدف شماست و چطور با امنیت و پایداری اسکریپینگ را انجام دهید.
آسان اسکریپ آسان اسکریپ
1405-04-01

مقدمه

در این مقاله عملی یاد می‌گیریم چطور با Scrapy به صفحات لاگین وارد شویم و داده‌های پشت احراز هویت را استخراج کنیم. ابتدا روش‌شناسی تحلیل فرم لاگین را توضیح می‌دهیم، سپس سه روش رایج (ارسال فرم ساده، ارسال فرم به همراه داده‌های پنهان و استفاده از مرورگر headless) را با مثال‌های پایتون و نکات فنی پوشش می‌دهیم. در انتها بهترین روش‌ها برای کاهش ریسک بلاک شدن و ملاحظات حقوقی را مرور می‌کنیم.

گام اول: تحلیل فرایند لاگین

قبل از نوشتن هر کدی باید فرایند لاگین سایت هدف را با ابزارهای توسعه‌دهنده مرورگر بررسی کنید. مراحل کلی:

  • مشاهده آدرس (URL) ای که درخواست لاگین را دریافت می‌کند.
  • بررسی Payload (داده‌های ارسال‌شده) در درخواست POST یا XHR.
  • بررسی هدرها و کوکی‌هایی که درخواست لاگین نیاز دارد.

هدف این مرحله: تعیین این که آیا سایت فقط نام‌کاربری/رمز عبور می‌خواهد، یا توکن‌های پنهان (مثل CSRF) یا داده‌های تولیدشده سمت کلاینت و حتی رمزنگاری‌شده دارد.

روش ۱: ارسال ساده با FormRequest

ایده کلی: اگر سایت صرفاً فیلدهای نام‌کاربری و رمز عبور را دریافت می‌کند، کافی است یک درخواست POST مشابه فرم ارسال کنیم. این روش سریع‌ترین و ساده‌ترین است اما این روزها کم پیش می‌آید که تنها همین داده‌ها لازم باشند.

مثال ساده (ورودی‌ها: آدرس لاگین، ایمیل و پسورد — خروجی: callback برای ادامهٔ اسکریپ):

from scrapy import Spider
from scrapy.http import FormRequest

class SimpleLoginSpider(Spider):
    name = 'simple_login'

    def start_requests(self):
        login_url = 'http://example.com/login'
        # formdata: دیکشنری فیلدهای فرم
        yield FormRequest(login_url, formdata={'email': 'you@example.com', 'password': 'secret'}, callback=self.start_scraping)

    def start_scraping(self, response):
        # response مربوط به صفحه بعد از لاگین است
        # از اینجا scraping صفحات پشت لاگین را آغاز کنید
        pass

چه کار می‌کند (خط‌به‌خط):

  • start_requests: درخواست ابتدایی به صفحهٔ لاگین می‌فرستد.
  • FormRequest: داده‌های فرم را با روش POST ارسال می‌کند و جلسه (cookies) را درون Scrapy مدیریت می‌کند.
  • start_scraping: callback که پس از لاگین فراخوانی می‌شود و ادامهٔ خزیدن را انجام می‌دهد.

محدودیت‌ها: اگر سایت نیاز به CSRF یا داده‌های پنهان یا رمزنگاری سمت کلاینت داشته باشد این روش ناکافی است.

روش ۲: FormRequest با استخراج داده‌های پنهان (مثل CSRF)

ایده: ابتدا صفحهٔ لاگین را GET می‌کنیم، توکن‌های پنهان (مثلاً csrf_token) را استخراج کرده و سپس با FormRequest.from_response فرم را تکمیل و ارسال می‌کنیم.

import scrapy
from scrapy import Spider
from scrapy.http import FormRequest

class HiddenDataLoginSpider(Spider):
    name = 'hidden_data_login'

    def start_requests(self):
        login_url = 'http://quotes.toscrape.com/login'
        yield scrapy.Request(login_url, callback=self.login)

    def login(self, response):
        # استخراج توکن CSRF از HTML اولیه
        token = response.css('form input[name=csrf_token]::attr(value)').get()

        # ارسال فرم همراه با توکن و باقی فیلدها
        return FormRequest.from_response(response,
                                         formdata={'csrf_token': token, 'username': 'foobar', 'password': 'foobar'},
                                         callback=self.start_scraping)

    def start_scraping(self, response):
        # اکنون session لاگین شده و می‌توانید ادامه دهید
        pass

توضیحات عملی و نکات:

  • اگر توکن‌ها در HTML اولیه وجود داشته باشند این روش قابل اعتماد و سبک است.
  • همیشه بررسی کنید که نام فیلدها در HTML با چیزی که در formdata می‌فرستید مطابقت داشته باشد.
  • استفاده از FormRequest.from_response کمک می‌کند فیلدهای مخفی فرم به صورت خودکار شناسایی شوند؛ اما گاهی باید صریحاً مقادیر را تعیین کنید.

روش ۳: استفاده از مرورگر headless (مثال با Scrapy + Splash)

چه زمانی لازم است: وقتی سایت از جاوااسکریپت برای تولید مقادیر مهمِ لاگین (مثل metadata1، aaToken یا رمزنگاری پسورد) استفاده می‌کند؛ یا جریان تأیید دو مرحله‌ای و صفحات متعدد دارد. در این موارد بهتر است از مرورگر headless برای انجام تعاملات استفاده کنید و سپس کوکی‌ها را به جلسات Scrapy منتقل کنید.

استراتژی کلی:

  1. با Splash یا هر مرورگر headless وارد شوید.
  2. کوکی‌های session را استخراج کنید.
  3. با همین کوکی‌ها درخواست‌های بعدی Scrapy را ارسال کنید تا از مزایای Scrapy (pipeline، concurrency کنترل‌شده، parserها) استفاده کنید.

نمونهٔ Lua script (که در Splash اجرا می‌شود) و Spider پایتون:

-- lua: تعامل ساده با فرم‌ها و بازگرداندن html و کوکی‌ها
function main(splash, args)
  splash:init_cookies(splash.args.cookies)
  assert(splash:go(args.url))
  assert(splash:wait(1))
  splash:set_viewport_full()

  local email_input = splash:select('input[name=email]')
  email_input:send_text('EMAIL@EXAMPLE.COM')
  assert(splash:wait(1))
  local continue_btn = splash:select('input[id=continue]')
  continue_btn:click()
  assert(splash:wait(2))

  local password_input = splash:select('input[name=password]')
  password_input:send_text('PASSWORD')
  assert(splash:wait(1))
  local sign_in = splash:select('input[id=signInSubmit]')
  sign_in:click()
  assert(splash:wait(3))

  return { html = splash:html(), url = splash:url(), cookies = splash:get_cookies() }
end
import scrapy
from scrapy_splash import SplashRequest

lua_script = '''
-- (قرار دادن همان کد lua بالا در اینجا)
'''

class AmazonLoginSpider(scrapy.Spider):
    name = 'amazon_login'

    def start_requests(self):
        signin_url = 'https://www.example.com/ap/signin'
        yield SplashRequest(url=signin_url, callback=self.after_login, endpoint='execute', args={'lua_source': lua_script, 'width': 1000})

    def after_login(self, response):
        # تبدیل لیست کوکی‌ها به دیکشنری name:value
        cookies_dict = {c['name']: c['value'] for c in response.data.get('cookies', [])}

        # حالا با همان کوکی‌ها می‌توان درخواست‌های معمول Scrapy را ارسال کرد
        yield scrapy.Request('https://www.example.com/', cookies=cookies_dict, callback=self.parse)

    def parse(self, response):
        # پردازش صفحات لاگین‌شده
        with open('response.html', 'wb') as f:
            f.write(response.body)

تنظیمات مورد نیاز برای فعال‌سازی Splash در settings.py (نمونه):

# settings.py (نمونه)
SPLASH_URL = 'http://localhost:8050'

DOWNLOADER_MIDDLEWARES = {
    'scrapy_splash.SplashCookiesMiddleware': 723,
    'scrapy_splash.SplashMiddleware': 725,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}

SPIDER_MIDDLEWARES = {
    'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}

DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

نکات فنی مهم:

  • استفاده از headless مرورگر، ساده‌ترین راه برای کنار زدن منطق پیچیدهٔ JS است اما هزینهٔ اجرای آن (منابع و زمان) بیشتر است.
  • بعد از ورود با مرورگر، استخراج کوکی‌ها و بازاستفادهٔ آن‌ها با درخواست‌های Scrapy بهترین ترکیب «پایایی + کارایی» را می‌دهد.
  • اگر داده‌ها با رمزنگاری کلاینت تولید می‌شوند، معکوس‌سازی JS خیلی هزینه‌بر و ناپایدار است.

چگونه پس از لاگین بلاک نشویم

لاگین شدن احتمال شناسایی شدن را افزایش می‌دهد چون همهٔ درخواست‌ها به یک حساب کاربری مرتبط هستند. نکات عملی برای کاهش ریسک:

  • چند حساب: تقسیم بار روی چند حساب تا از ارسال درخواست‌های زیاد از یک حساب جلوگیری شود.
  • آی‌پی ثابت برای هر حساب: تغییر مکرر آی‌پی هنگام لاگین می‌تواند محرک هشدارهای امنیتی باشد. پروکسی‌های مسکونی یا دیتاسنتر بسته به هدف انتخاب شوند.
  • پروفایل مرورگر و User-Agent: از UA واقعی و ثابت استفاده کنید؛ UA پیش‌فرض Scrapy مشخص و آشکار است.
  • تک‌ترد و تأخیر بین درخواست‌ها: CONCURRENT_REQUESTS=1 و DOWNLOAD_DELAY (مثلاً 10 ثانیه با نوسان) رفتار انسانی‌تری شبیه‌سازی می‌کنند.
  • الگوهای رفتاری واقعی: مسیرهای بازدید را شبیه کاربر واقعی طراحی کنید (مثلاً جستجو → نتایج → بازدید محصول).

مثال‌های تنظیم:

# settings.py
CONCURRENT_REQUESTS = 1
DOWNLOAD_DELAY = 10  # می‌تواند با randomization ترکیب شود

ریسک‌ها و ملاحظات حقوقی

اسکریپینگ پشت لاگین ریسک‌های بیشتری دارد نسبت به صفحات عمومی. نکات کلیدی:

  • ممکن است داده‌های شخصی (نام، ایمیل، کارت) با حساب مرتبط باشند؛ در صورت فاش شدن مسئولیت حقوقی دارید.
  • خطر بسته شدن یا محروم شدن حساب‌ها: سایت ممکن است حساب‌ها را مسدود یا حذف کند و در مواردی از پیگیری قانونی استفاده کند.
  • قوانین و Terms of Service: قبل از اسکریپینگ پشت لاگین، حتماً شرایط سرویس را مطالعه کرده و ارزیابی حقوقی انجام دهید؛ در بسیاری از موارد، اقدام به اسکریپینگ خلاف قوانین سایت است.

جمع‌بندی و توصیه‌های عملی

خلاصهٔ عملی:

  • ابتدا فرایند لاگین را در Developer Tools تحلیل کنید.
  • اگر فقط نام‌کاربری/پسورد لازم است از FormRequest استفاده کنید.
  • اگر توکن‌های مخفی در HTML وجود دارند، صفحه را GET کنید و آن‌ها را استخراج کرده سپس ارسال کنید.
  • برای فرم‌های تولیدشده با JS یا رمزنگاری‌شده، از مرورگر headless استفاده کنید و سپس کوکی‌ها را به Scrapy منتقل کنید.
  • همیشه ملاحظات ضدربات: پروکسی مناسب، UA واقعی، تاخیر و الگوهای انسانی را به کار بگیرید.
  • پیش از کار، ریسک‌های حقوقی و محرمانگی را بررسی کنید.

با رعایت این چارچوب‌ها می‌توانید عملاً اکثر صفحات لاگین را مدیریت کنید و از توان Scrapy در پردازش و ذخیرهٔ داده بهره ببرید بدون اینکه پایداری یا امنیت پروژه را به خطر بیندازید.

مطالب مرتبط

مقاله‌های مرتبط