بازگشت به وبلاگ

نحوه حل مشکلات کوکی از طریق پروکسی

کوکی‌ها اغلب منبع مشکلاتی هستند هنگام کار از طریق پروکسی. بیاموزید چرا این اتفاق می‌افتد و چگونه می‌توانید آن‌ها را به درستی پیکربندی کنید.

📅۱۷ آذر ۱۴۰۴
```html

نحوه رفع مشکلات کوکی‌ها از طریق پروکسی

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

چرا کوکی‌ها هنگام استفاده از پروکسی از دست می‌روند

هنگامی که درخواستی را از طریق پروکسی ارسال می‌کنید، یک گره میانی بین کلاینت شما و سرور هدف قرار می‌گیرد. این مسائل متعددی ایجاد می‌کند:

  • آدرس‌های IP متفاوت برای یک جلسه. سرور ممکن است متوجه شود که درخواست‌ها از آدرس‌های مختلف می‌آیند و کوکی‌ها را به‌عنوان مشکوک رد کند.
  • از دست رفتن سرصحافه‌های Set-Cookie. تنظیم نادرست پروکسی ممکن است سرصحافه‌های Set-Cookie را به کلاینت منتقل نکند.
  • عدم تطابق دامنه و مسیر. اگر پروکسی سرصحافه Host را بازنویسی کند، کوکی‌ها ممکن است به دلیل عدم تطابق دامنه ذخیره نشوند.
  • عدم وجود ذخیره‌سازی وضعیت. اگر هر درخواست را بدون ذخیره کوکی‌ها جداگانه ارسال کنید، جلسه از دست خواهد رفت.

کوکی جار یک ذخیره‌گاه کوکی است که به‌طور خودکار مدیریت ارسال و دریافت آن‌ها را انجام می‌دهد. به‌جای افزودن دستی سرصحافه Cookie به هر درخواست، اجازه می‌دهید کتابخانه این کار را به‌طور خودکار انجام دهد.

اکثر کلاینت‌های HTTP دارای پشتیبانی داخلی برای کوکی جار هستند:

import requests
from requests.cookies import RequestsCookieJar

# جار برای ذخیره‌سازی کوکی‌ها ایجاد می‌کنیم
jar = RequestsCookieJar()

# درخواست اول — سرور Set-Cookie ارسال می‌کند
response1 = requests.get(
    'https://example.com/login',
    cookies=jar,
    proxies={'https': 'http://proxy.example.com:8080'}
)

# کوکی‌ها به‌طور خودکار در جار ذخیره شدند
print(jar)

# درخواست دوم — کوکی‌ها به‌طور خودکار ارسال می‌شوند
response2 = requests.get(
    'https://example.com/dashboard',
    cookies=jar,
    proxies={'https': 'http://proxy.example.com:8080'}
)

بدون جار باید به‌صورت دستی Set-Cookie را تجزیه کنید و آن‌ها را به درخواست بعدی اضافه کنید — این ناپایدار و دشوار است.

ذخیره کوکی‌ها بین درخواست‌ها

اگر اسکریپت شما مدت طولانی کار می‌کند یا نیاز دارید جلسه را پس از بارگذاری مجدد بازیابی کنید، کوکی‌ها را در یک فایل ذخیره کنید:

import requests
from http.cookiejar import LWPCookieJar

# جار با ذخیره‌سازی در فایل ایجاد می‌کنیم
jar = LWPCookieJar('cookies.txt')

# کوکی‌های قدیمی را بارگذاری می‌کنیم اگر وجود داشته باشند
try:
    jar.load(ignore_discard=True, ignore_expires=True)
except FileNotFoundError:
    pass

# جار را در درخواست‌ها استفاده می‌کنیم
response = requests.get(
    'https://example.com/login',
    cookies=jar,
    proxies={'https': 'http://proxy.example.com:8080'}
)

# کوکی‌های به‌روز شده را ذخیره می‌کنیم
jar.save(ignore_discard=True, ignore_expires=True)

پرچم‌های ignore_discard=True و ignore_expires=True اجازه می‌دهند حتی کوکی‌های موقت را ذخیره کنید.

مشکلات مربوط به اتصال دامنه کوکی‌ها

کوکی‌ها دارای ویژگی Domain هستند که تعیین می‌کند برای کدام دامنه‌ها ارسال خواهند شد. مشکلات زمانی بروز می‌کند که:

  • پروکسی Host را بازنویسی می‌کند. اگر پروکسی سرصحافه Host را تغییر دهد، کوکی جار ممکن است کوکی را به‌عنوان متعلق به دامنه دیگری رد کند.
  • زیردامنه‌ها مطابقت ندارند. کوکی برای example.com ممکن است به api.example.com ارسال نشود.
  • مسیر مطابقت ندارد. کوکی برای /api به /admin ارسال نخواهد شد.

ویژگی‌های کوکی را به‌این‌گونه بررسی کنید:

import requests

response = requests.get(
    'https://example.com',
    proxies={'https': 'http://proxy.example.com:8080'}
)

# تمام کوکی‌ها را نمایش می‌دهیم
for cookie in response.cookies:
    print(f"Name: {cookie.name}")
    print(f"Value: {cookie.value}")
    print(f"Domain: {cookie.domain}")
    print(f"Path: {cookie.path}")
    print(f"Secure: {cookie.secure}")
    print(f"HttpOnly: {cookie.has_nonstandard_attr('HttpOnly')}")
    print("---")

اگر Domain خیلی محدود است، سعی کنید کوکی‌ها را به‌صورت صریح مشخص کنید به‌جای مدیریت خودکار:

headers = {
    'Cookie': 'session_id=abc123; user_token=xyz789'
}

response = requests.get(
    'https://example.com/api',
    headers=headers,
    proxies={'https': 'http://proxy.example.com:8080'}
)

پرچم‌های Secure و HttpOnly

پرچم Secure به‌معنای این است که کوکی تنها از طریق HTTPS ارسال می‌شود. اگر از پروکسی HTTP برای دسترسی به منبع HTTPS استفاده می‌کنید، مطمئن شوید که اتصال به پروکسی محافظت‌شده است یا پروکسی به‌درستی HTTPS را پروکسی می‌کند.

پرچم HttpOnly دسترسی به کوکی از JavaScript را ممنوع می‌کند. این بر ارسال کوکی در درخواست‌ها تأثیر نمی‌گذارد، اما مهم است که بدانید نمی‌توانید چنین کوکی‌هایی را از مرورگر بخوانید.

هنگام کار با پروکسی‌های مسکونی مطمئن شوید که:

  • پروکسی از HTTPS پشتیبانی می‌کند (روش CONNECT)
  • گواهی‌ها معتبر هستند (از verify=False در تولید استفاده نکنید)
  • سرصحافه‌ها توسط پروکسی بازنویسی نمی‌شوند

نمونه‌های عملی با کد

نمونه 1: ورود با ذخیره‌سازی جلسه

import requests
from requests.cookies import RequestsCookieJar

jar = RequestsCookieJar()
proxy = 'http://proxy.example.com:8080'

# ورود
login_response = requests.post(
    'https://example.com/login',
    data={'username': 'user', 'password': 'pass'},
    cookies=jar,
    proxies={'https': proxy}
)

if login_response.status_code == 200:
    print("ورود موفق")
    
    # جلسه ذخیره‌شده را استفاده می‌کنیم
    dashboard = requests.get(
        'https://example.com/dashboard',
        cookies=jar,
        proxies={'https': proxy}
    )
    print(dashboard.text)

نمونه 2: پردازش درخواست‌های متعدد

import requests
from http.cookiejar import LWPCookieJar
import time

jar = LWPCookieJar('session.txt')
try:
    jar.load(ignore_discard=True)
except:
    pass

proxy = 'http://proxy.example.com:8080'
urls = [
    'https://example.com/page1',
    'https://example.com/page2',
    'https://example.com/page3'
]

for url in urls:
    response = requests.get(
        url,
        cookies=jar,
        proxies={'https': proxy},
        timeout=10
    )
    print(f"{url}: {response.status_code}")
    jar.save(ignore_discard=True)
    time.sleep(1)  # سرور را بیش‌بار نکنید

نمونه 3: انتقال صریح کوکی‌ها در صورت مشکل

import requests

proxy = 'http://proxy.example.com:8080'

# اگر مدیریت خودکار کار نکند
cookies_dict = {
    'session_id': 'abc123def456',
    'user_pref': 'dark_mode'
}

headers = {
    'User-Agent': 'Mozilla/5.0...',
    'Cookie': '; '.join([f"{k}={v}" for k, v in cookies_dict.items()])
}

response = requests.get(
    'https://example.com/api/data',
    headers=headers,
    proxies={'https': proxy}
)

print(response.json())

رفع عیب مشکلات کوکی‌ها

اگر کوکی‌ها کار نکنند، از این ابزارها استفاده کنید:

ابزار هدف
requests.Session به‌طور خودکار کوکی‌ها را برای تمام درخواست‌ها در جلسه مدیریت می‌کند
logging DEBUG را برای requests فعال کنید تا تمام سرصحافه‌ها را ببینید
Fiddler / Charles ترافیک را قطع کنید و سرصحافه‌های Set-Cookie و Cookie را ببینید
curl -v همان چیز را از طریق پروکسی از خط فرمان آزمایش کنید

برای رفع عیب، ثبت‌کردن را فعال کنید:

import logging
import requests

logging.basicConfig(level=logging.DEBUG)

# اکنون تمام درخواست‌ها سرصحافه‌ها و کوکی‌ها را نمایش می‌دهند
response = requests.get(
    'https://example.com',
    proxies={'https': 'http://proxy.example.com:8080'}
)

بررسی کنید که پروکسی کوکی‌ها را مسدود نمی‌کند:

curl -v -x http://proxy.example.com:8080 https://example.com

# سرصحافه‌ها را ببینید:
# Set-Cookie: ... (باید وجود داشته باشند)
# Cookie: ... (باید در درخواست بعدی ارسال شوند)

نکته: اگر از پروکسی‌های مسکونی استفاده می‌کنید، به‌یاد داشته باشید که آن‌ها ممکن است IP را بین درخواست‌ها تغییر دهند. مطمئن شوید که منطق مدیریت کوکی‌های شما این را در نظر می‌گیرد — برخی سرورها درخواست‌ها را از IP‌های مختلف در یک جلسه رد می‌کنند.

خلاصه

مشکلات کوکی هنگام کار از طریق پروکسی با تنظیم صحیح حل می‌شوند:

  • از کوکی جار برای مدیریت خودکار کوکی‌ها استفاده کنید
  • کوکی‌ها را بین درخواست‌ها در فایل ذخیره کنید
  • اتصال دامنه و ویژگی‌های Path را بررسی کنید
  • از پشتیبانی HTTPS پروکسی اطمینان حاصل کنید
  • برای شناسایی مشکلات از رفع عیب استفاده کنید

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

```