خانه/مقالات/بهینه‌سازی هدرها برای اسکریپینگ پایتون
برنامه نویسی
پروکسی و چرخش IP
برگشت به مقاله‌ها

بهینه‌سازی هدرها برای اسکریپینگ پایتون

بهینه‌سازی هدرها برای اسکریپینگ پایتون
این مقاله آموزش عملی بهینه‌سازی هدرها برای اسکریپینگ با پایتون را ارائه می‌دهد: از استخراج هدرهای مرورگر و شبیه‌سازی آن‌ها، تا حفظ ترتیب هدرها، گردش User-Agent و بررسی هدرهای اضافه‌شده توسط پراکسی. با مثال‌های پایتون و نکات فنی می‌توانید هدرهای خود را امن‌تر و مؤثرتر مدیریت کنید.
آسان اسکریپ آسان اسکریپ
1405-06-29

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

مقدمه

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

چرا باید از هدرهای واقعی مرورگر استفاده کنیم

بسیاری از کتابخانه‌های HTTP به‌صورت پیش‌فرض هدرهای ساده یا هدرهایی که خودِ کتابخانه را معرفی می‌کنند ارسال می‌کنند؛ مثلا requests در هدر User-Agent عبارتی شبیه python-requests/2.x می‌فرستد که برای سرور نشانهٔ یک بات است. سرورها با قوانین ساده یا الگوریتم‌های پیچیده متوجه این تفاوت می‌شوند و می‌توانند درخواست‌ها را مسدود کنند.

مثال پایه: ارسال یک درخواست ساده با requests. این قطعه کد ورودی: آدرس هدف؛ خروجی: متن پاسخ (که شامل هدرهای دریافت‌شده از دید سرور است).

import requests

r = requests.get('http://httpbin.org/headers')
print(r.text)

توضیح خط‌به‌خط:

  • خط 1: کتابخانه requests را وارد می‌کنیم.
  • خط 3: با requests.get یک GET ساده به http://httpbin.org/headers می‌زنیم؛ این سرویس بازتاب هدرها را برمی‌گرداند.
  • خط 4: r.text محتوای متنی بدن پاسخ را چاپ می‌کند (معمولاً JSON حاوی هدرهایی که سرور دیده).

با اجرای این کد معمولاً هدرهای محدودی مثل User-Agent با مقدار کتابخانه و چند هدر دیگر خواهید دید که واضحاً شبیه ترافیک انسانی نیستند و ریسک بلاک شدن را بالا می‌برند.

شبیه‌سازی هدرهای مرورگر واقعی

هدف این است که درخواست‌های اسکریپر تا حد امکان شبیه درخواست‌هایی باشد که یک مرورگر واقعی می‌سازد؛ یعنی مجموعه هدرها، مقادیر آن‌ها و حتی ترتیب ارسال باید مشابه مرورگر باشد. مرورگرها هدرهای زیادی می‌فرستند: User-Agent، Accept، Accept-Language، Accept-Encoding، sec-ch-ua و Sec-Fetch-* و غیره.

نمونه‌ای از هدرهای یک Chrome روی macOS (نمایش ساده‌شده):

Host: example.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... Chrome/99.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8

هر فیلد اطلاعاتی دربارهٔ محیط کاربر می‌دهد؛ برای مثال sec-ch-ua-platform سیستم‌عامل را نشان می‌دهد و Accept-Language زبان‌های ترجیحی را مشخص می‌کند. اگر هدرها با یکدیگر ناسازگار باشند (مثلاً User-Agent مربوط به Chrome اما sec-ch-ua مربوط به Firefox) احتمال شناسایی بالاتر می‌رود.

تولید و استخراج هدرها از مرورگر

رایج‌ترین روش گرفتن هدرهای واقعی، استفاده از ابزار توسعه‌دهندهٔ مرورگر است:

  1. صفحه هدف را در مرورگر باز کنید و DevTools را باز نمایید (Inspect).
  2. در تب Network درخواست‌ها را انتخاب و اولین درخواست صفحه را کلیک کنید.
  3. در بخش Headers بخش Request Headers را کپی کنید و هدرهایی که خیلی اختصاصی یا حاوی کوکی/توکن هستند را حذف کنید.

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

Host
Connection
Cache-Control
sec-ch-ua
sec-ch-ua-mobile
sec-ch-ua-platform
Upgrade-Insecure-Requests
User-Agent
Accept
Sec-Fetch-Site
Sec-Fetch-Mode
Sec-Fetch-User
Sec-Fetch-Dest
Accept-Encoding
Accept-Language

نکته عملی: برخی هدرها مثل cookie یا هدرهای مشخص کننده شناسهٔ کاربری را معمولاً نباید در درخواست‌های عمومی استفاده کنید مگر برای شبیه‌سازی نشست واقعی کاربر.

تضمین ترتیب صحیح هدرها

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

نمونهٔ ساده‌ای از تفاوت ترتیب (نمایش خلاصه‌شده):

-- Chrome on Windows --
Host
Connection
Cache-Control
sec-ch-ua
... 
User-Agent
Accept
Sec-Fetch-Site
...

-- Firefox on Windows --
Host
User-Agent
Accept
Accept-Language
Accept-Encoding
Connection
Upgrade-Insecure-Requests
...

چالش عملی: بعضی کلاینت‌ها همچون requests ممکن است ترتیب هدرها را بازنویسی کنند یا به شیوه‌ای ارسال نمایند که شما کنترل کامل روی ترتیب نداشته باشید. برای مقابله:

  • قبل از اتکا به یک پیاده‌سازی، با httpbin.org/headers یا سرویس مشابه آزمایش کنید تا ببینید سرور چه هدرهایی را واقعاً می‌بیند.
  • اگر کلاینت شما ترتیب را تغییر می‌دهد، از لایهٔ پایین‌تر (مثلاً urllib3، http.client یا کلاینت‌هایی که امکان ساخت درخواست خام را می‌دهند) استفاده کنید یا از راهکارهای مدیریت پراکسی بهره ببرید.
  • در صورت استفاده از requests، از PreparedRequest و Session امتحان کنید و نتایج را مقایسه نمایید؛ اما همیشه خروجی واقعی را در سرور هدف اعتبارسنجی کنید.

چرخاندن هدرها و User-Agent

برای اسکریپینگ در مقیاس، داشتن تنها یک هدر ثابت کافی نیست؛ باید مجموعه‌ای از هدرهای معتبر و پراکنده داشته باشید و برای هر درخواست یکی را انتخاب کنید تا الگوی شما شبیه ترافیک طبیعی شود. مهم‌تر از همه User-Agent است و باید با سایر هدرها سازگاری داشته باشد.

مثال سادهٔ گردش با requests (ورودی: لیستی از هدرها؛ خروجی: پاسخ هر URL):

import requests
from random import choice

# فرض می‌کنیم header_list یک لیست از دیکشنری‌های هدر معتبر است
header_list = [
    {"User-Agent": "Mozilla/5.0 ... Chrome/103.0", "Accept": "text/html,..."},
    {"User-Agent": "Mozilla/5.0 ... Firefox/103.0", "Accept": "text/html,..."}
]

urls = ["https://example.com/1", "https://example.com/2"]
for url in urls:
    h = choice(header_list)
    r = requests.get(url, headers=h)
    print(url, r.status_code)

توضیح:

  • header_list: لیستی از دیکشنری‌های هدر که از پیش جمع‌آوری و پاک‌سازی شده‌اند.
  • برای هر درخواست به‌صورت تصادفی یک مجموعه هدر انتخاب می‌کنیم و با آن می‌فرستیم.
  • به یاد داشته باشید که User-Agent باید با سایر فیلدها مطابقت داشته باشد (مثلاً sec-ch-ua و platform).

نکتهٔ عملکردی: اگر تعداد درخواست‌ها زیاد باشد، چرخاندن تنها User-Agent کافی نیست؛ باید زبان، Accept، و حتی ترکیب sec-ch-ua را نیز تغییر دهید تا پروفایل کاربران را شبیه‌سازی کنید.

نگه‌داشتن هدرها به‌روز

مرورگرها و User-Agentها دائماً آپدیت می‌شوند؛ بنابراین هدرهایی که امروز طبیعی به‌نظر می‌رسند ممکن است چند هفته بعد قدیمی شوند. توصیه‌ها:

  • به‌صورت دوره‌ای مجموعهٔ هدرها/User-Agentها را بازسازی کنید و از منابع معتبر لیست‌های رایج را بگیرید.
  • در صورت امکان اتوماسیون کنید: موقع راه‌اندازی اسکراپر، یک بار مجموعهٔ به‌روز هدرها را بارگیری کنید.

حذف هدرهای مضرِ اضافه‌شده توسط پراکسی

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

Forwarded
Proxy-Authorization
X-Forwarded-For
Proxy-Authenticate
X-Requested-With
From
X-Real-Ip
Via
True-Client-Ip
Proxy_Connection

برای بررسی اینکه پراکسی شما هدر اضافه نمی‌کند، می‌توانید چند درخواست از طریق آن پراکسی به یک سرویس بازتاب‌دهنده بزنید:

import requests
proxies = {"http": "http://PROXY:PORT", "https": "http://PROXY:PORT"}
r = requests.get('http://httpbin.org/headers', proxies=proxies, verify=False)
print(r.text)

توضیح:

  • این کد یک درخواست از طریق پراکسی می‌فرستد و خروجی JSON شامل هدرهایی که سرور هدف دیده را چاپ می‌کند.
  • اگر هدرهایی مانند X-Forwarded-For دیده شوند، نشان می‌دهد پراکسی شما اطلاعات ناخواسته اضافه می‌کند و باید با آن ارائه‌دهنده تماس بگیرید یا از پراکسی دیگری استفاده کنید.

مدیریت هدرها: دو رویکرد عملی

برای مدیریت و خودکارسازی تولید هدرها دو رویکرد معمول وجود دارد:

  1. API تولید هدر جعلیِ به‌روز: سرویس‌هایی مجموعه‌ای از هدرهای به‌روز و بهینه شده را برمی‌گردانند. شما می‌توانید در شروع اجرا یک بچ از هدرها دریافت و در طول اجرا چرخانده آن‌ها را استفاده کنید.
  2. راه‌حل پراکسی هوشمند: برخی پراکسی‌ها خودشان هدرها را برای هر درخواست بهینه می‌کنند و شما را از مدیریت دستی هدرها بی‌نیاز می‌کنند.

نمونهٔ پاسخ ساده‌شده یک API که لیستی از هدرها برمی‌گرداند (فرمت JSON نمایشی):

{
  "result": [
    {"user-agent": "Mozilla/5.0 ... Chrome/103.0", "accept": "text/html,...", "sec-ch-ua-platform": "Windows"},
    {"user-agent": "Mozilla/5.0 ... Chrome/103.0 (Linux)", "accept-language": "fr-CH,fr;q=0.9"}
  ]
}

نکات عملی در انتخاب بین این دو رویکرد:

  • اگر می‌خواهید حداکثر کنترل را داشته باشید و تنظیمات خاصی برای هر دامنه اعمال کنید، استفاده از API و مدیریت داخلی بهتر است.
  • اگر می‌خواهید ساده‌تر و مقیاس‌پذیرتر کار کنید و هزینهٔ زمان مهندسی را کاهش دهید، پراکسی‌های هوشمند می‌توانند کار شما را ساده کنند.

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

خلاصه نکات عملی که باید از آن‌ها پیروی کنید:

  • همیشه هدرهای واقعی مرورگر را شبیه‌سازی کنید؛ فقط تغییر User-Agent کافی نیست.
  • هدرها را از DevTools استخراج کنید، مقادیر خیلی خاص (مثل کوکی‌ها) را پاک کنید و ترتیب آن‌ها را حفظ نمایید.
  • برای مقیاس از مجموعه‌ای از هدرها و لیست User-Agent چرخان استفاده کنید و اطمینان حاصل کنید ترکیب‌ها منطقی و سازگارند.
  • پراکسی‌ها را تست کنید تا مطمئن شوید هدرهای ناخواسته اضافه نمی‌کنند؛ در صورت لزوم پراکسی را تغییر دهید یا تنظیمات آن را اصلاح کنید.
  • به‌صورت دوره‌ای هدرها و User-Agentها را به‌روز کنید یا از سرویس‌های مدیریتی/پراکسی هوشمند استفاده کنید تا نگهداری ساده‌تر شود.

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

آسان اسکریپ را در گوگل به‌عنوان منبع ترجیحی انتخاب کن

مقاله‌های جدید ما زودتر و پررنگ‌تر در نتایج گوگل و Discover برایت نمایش داده می‌شود. افزودن از تنظیمات گوگل

مطالب مرتبط

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