مقدمه
در این مقاله عملی برای توسعهدهندههای پایتون میانی، میآموزیم چطور یک اسکریپ Playwright بسازیم که کمترین شانسِ شناسایی شدن توسط ضدرباتها را داشته باشد. ابتدا مکانیسمهای تشخیص بات را مرور میکنیم، سپس تکنیکهای پراکسی، تغییرات در محیط مرورگر و تقلید رفتار انسان را گامبهگام پیادهسازی میکنیم. در پایان روشهای تست، مدیریت خطا و نگارش عمومیِ بهترینروشها را میبینید.
بعد از خواندن این مقاله باید بتوانید: توضیح دهید سایتها چگونه بات را تشخیص میدهند، یک کانتکست Playwright در پایتون تنظیم کنید، جاویژههایی برای تقلید رفتار انسان و مدیریت CAPTCHA و پروکسی پیادهسازی کنید و اسکریپهای خود را آزمایش و پایش کنید.
چگونه سایتها بات را تشخیص میدهند
درک روشهای تشخیص مهم است چون راهحلها بر اساس همان حملات طراحی میشوند:
- تحلیل IP و نرخسنجی: درخواستهای زیاد از یک IP یا الگوی غیرمعمول میتواند منجر به بلاک یا CAPTCHA شود.
- فینگرپرینت مرورگر: جمعآوری اطلاعاتی مثل نسخهٔ مرورگر، رزولوشن، پلاگینها، WebGL و سایر مشخصهها برای ساخت یک شناسه یکتا.
- شناسایی headless: وجود فلگهایی مثل
navigator.webdriverیا آرگومانهای راهاندازی که نشاندهنده اتوماسیوناند. - تحلیل رفتار کاربر: الگوهایی مانند تایپ سریع، کلیکهای پشتسرهم یا حرکت موس یکنواخت که غیرطبیعی هستند.
برای هر مورد باید یک یا چند راهحل متناسب طراحی شود: پراکسی چرخان، تغییر هدرها، حذف/اصلاح فلگهای اتوماسیون، و تولید رفتار انسانمانند.
تکنیکهای پایه برای «بدونشناسایی» کردن Playwright
این بخش شامل تکنیکهایی است که تقریباً همیشه در ترکیب استفاده میشوند.
تنظیم User-Agent، viewport و locale
یک user-agent معتبر که با مشخصات viewport و locale سازگار باشد از ناسازگاری فینگرپرینت جلوگیری میکند. مثال زیر راهاندازی کانتکست در پایتون را نشان میدهد:
from playwright.async_api import async_playwright
async def example():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context(
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
viewport={'width': 1280, 'height': 720},
locale='en-US',
timezone_id='America/New_York'
)
page = await context.new_page()
await page.goto('https://example.com')
await browser.close()شرح: ورودیهای تابع شامل user_agent، viewport و locale هستند؛ اینها خروجیِ فینگرپرینت را تغییر میدهند تا با یک کاربر واقعی منطبق شود.
فلگهای راهاندازی مرورگر (automation flags)
بسیاری از تشخیصها از فلگهای کروم/کرومیوم استفاده میکنند. حذف یا اصلاح آنها کمک میکند. در زمان لانچ کردن میتوان آرگومانها را اضافه کرد:
browser = await p.chromium.launch(
headless=False,
args=[
'--disable-blink-features=AutomationControlled',
'--disable-extensions',
'--disable-infobars',
'--no-first-run',
'--enable-webgl',
'--enable-accelerated-2d-canvas'
]
)نکتهٔ امنیتی: برخی از فلگها ممکن است با سیاستهای سایت تداخل داشته باشند؛ هر تغییر را آزمایش کنید.
فعالسازی WebGL و hardware acceleration
وجود WebGL و پارامترهای گرافیکی سازگار به سایتها نشان میدهد که مرورگر امکانات سختافزاری دارد—معمولاً سرورها روی مرورگرهای واقعی حساب باز میکنند.
استفاده از پراکسیهای Residential و چرخان
پراکسی مسکونی بهتر از دیتاسنتر است چون IP از ISP واقعی میآید و تشخیص آن سختتر است. برای اتصال پراکسی در Playwright پایتون:
browser = await p.chromium.launch(proxy={
'server': 'http://residential-proxy.example:3128',
'username': 'user',
'password': 'pass'
})برای چرخش IP معمولاً از یک لایه پراکسی مدیریتی یا پروکسیآگروگیتور استفاده میکنیم که درخواستها را به IPهای مختلف ارسال میکند.
تقلید رفتار انسان (Mouse, Typing, Scrolling)
یکی از موثرترین بخشها شبیهسازی تعاملات انسانی است: تایپ با تأخیرهای متغیر، حرکت موس با الگوی غیرقابلپیشبینی و اسکرول تدریجی. مثال پیادهسازی ساده در پایتون:
import random
import asyncio
from playwright.async_api import async_playwright
async def human_type(page, selector, text):
for ch in text:
await page.type(selector, ch)
await asyncio.sleep(random.uniform(0.05, 0.25))
async def random_mouse_movements(page, moves=5):
for _ in range(moves):
x = random.randint(0, 1000)
y = random.randint(0, 800)
await page.mouse.move(x, y)
await asyncio.sleep(random.uniform(0.05, 0.3))
async def demo():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context(viewport={'width':1280,'height':720})
page = await context.new_page()
await page.goto('https://example.com')
await random_mouse_movements(page)
await human_type(page, 'input[name="q"]', 'hello world')
await browser.close()
# run demo with an asyncio loopتوضیح: human_type و random_mouse_movements ورودیهای ساده میگیرند و رفتار را تقسیم میکنند تا طبیعیتر بهنظر برسد.
استفاده از نسخههای fortified و پلاگینهای stealth
برای برخی زبانها (بهویژه Node.js) کتابخانههایی مانند playwright-extra یا پلاگینهای puppeteer-extra-plugin-stealth وجود دارند که مجموعهای از اصلاحات را خودکار میکنند. اگر از پایتون استفاده میکنید ممکن است مجبور شوید برخی از این تکنیکها را دستی اعمال کنید یا از ابزارهای هاستشده استفاده کنید.
// مثال JS: استفاده از playwright-extra + stealth (برای درک ایده)
const { chromium } = require('playwright-extra')
const stealth = require('puppeteer-extra-plugin-stealth')()
chromium.use(stealth)
chromium.launch({ headless: true }).then(async browser => {
const page = await browser.newPage()
await page.goto('https://bot.sannysoft.com')
await browser.close()
})توضیح: اینجا مثال JS برای درک رفتار و مقایسه آمده؛ در پایتون معادل کاملِ همین پکیجها همیشه در دسترس نیست، بنابراین «فورتِفای» دستی با ترکیب فلگها، هدرها و تعاملهای انسانی معمولتر است.
تست و ارزیابی اسکریپ
برای بررسی میزان «انسانماندگی» اسکریپ از سایتهایی مثل bot.sannysoft و bot.incolumitas استفاده کنید. عبارتهای مهم برای استخراج امتیازها را در صفحه بخوانید و خروجی را لاگ کنید. نمونهٔ سادهٔ بررسی محتوای صفحه:
# نمونهٔ ساده برای خواندن خروجی تست از یک صفحه
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context()
page = await context.new_page()
await page.goto('https://bot.incolumitas.com')
# خواندن محتوای عناصر مربوط به تستها
new_tests = await page.eval_on_selector('#new-tests', 'el => el.textContent')
print(new_tests)
await browser.close()مقایسهٔ نتایج قبل و بعد از فورتِفای نشان میدهد چه تکنیکهایی بیشترین تأثیر را دارند (مثلاً افزایش behavioralClassificationScore).
مدیریت خطا، retry و پایداری
اسکریپها در مواجهه با شبکه ناپایدار یا پاسخهای غیرمنتظره باید مقاوم باشند. یک الگوی رایج استفاده از حلقه retry با backoff است:
import asyncio
async def run_with_retries(func, max_retries=5):
for attempt in range(1, max_retries+1):
try:
return await func()
except Exception as e:
print(f'Attempt {attempt} failed:', e)
if attempt == max_retries:
raise
await asyncio.sleep(2 ** attempt)
# استفاده: await run_with_retries(lambda: your_async_task())نکته: لاگبرداری و متریکبرداری به شما کمک میکند الگوهای خطا را تشخیص دهید.
برخورد با CAPTCHA
CAPTCHAها چالشبرانگیزند و سه رویکرد اصلی وجود دارد:
- اجتناب: با تقلید رفتار طبیعی و پراکسی مناسب تلاش کنید از برخوردن به CAPTCHA جلوگیری کنید.
- مداخلهٔ انسانی: اجرای اسکریپ را متوقف و از یک نیروی انسانی برای حل CAPTCHA کمک بگیرید.
- سرویسهای ثالث: سرویسهایی مانند 2Captcha یا Anti-Captcha وجود دارند که با آپلود تصویر یا پارامترهای CAPTCHA پاسخ را برمیگردانند (با هزینه و ریسکهای حریم خصوصی).
نمونهٔ پردازش CAPTCHA با 2Captcha در پایتون (خلاصه):
import requests
import time
API_KEY = 'YOUR_2CAPTCHA_KEY'
def submit_captcha(base64_image):
res = requests.post('http://2captcha.com/in.php', data={
'key': API_KEY,
'method': 'base64',
'body': base64_image
})
if res.text.split('|')[0] != 'OK':
raise Exception('submit failed')
return res.text.split('|')[1]
def poll_solution(captcha_id, timeout=120):
t0 = time.time()
while time.time() - t0 < timeout:
res = requests.get('http://2captcha.com/res.php', params={'key': API_KEY, 'action':'get', 'id':captcha_id})
if res.text == 'CAPCHA_NOT_READY':
time.sleep(5)
continue
if res.text.split('|')[0] == 'OK':
return res.text.split('|')[1]
raise Exception('error solving')
# مراحل در اسکریپ: گرفتن screenshot از عنصر CAPTCHA، ارسال base64 به submit_captcha و سپس poll_solutionهشدار: استفاده از سرویسهای حل CAPTCHA ممکن است قوانین سرویس هدف را نقض کند؛ قبل از پیادهسازی بررسی حقوقی و اخلاقی انجام دهید.
مطالعهٔ موردی خلاصه: عبور از دفاع G2
خلاصهٔ تجربهٔ عملی: یک اسکریپ ساده بدون فورتِفای سریعاً با CAPTCHA یا صفحات ناقص مواجه میشود. با افزودن user-agent معتبر، کوکیِ جلسه (session cookie)، تغییر viewport، و کمی تعامل انسانی (تایپ و حرکت موس)، صفحه بهدرستی لود شد و دادهها استخراج شدند. نکتهٔ کلیدی: ترکیب تکنیکها بهتر از تکیکار کردن است.
بهترینروشها و ملاحظات اخلاقی
- رعایت قوانین و Terms of Service : قبل از اسکریپ کردن، شرایط سایت را بررسی کنید و در صورت نیاز مجوز بگیرید.
- محدود کردن نرخ درخواست : از throttling و backoff استفاده کنید تا به زیرساخت سایت فشار وارد نکنید.
- حفظ حریم خصوصی : از جمعآوری یا ذخیرهسازی اطلاعات حساس خودداری کنید یا آن را بهدرستی محافظت کنید.
- پایش و لاگینگ : خطاها، تغییرات ساختار صفحه و نرخ بلاک را مانیتور کنید و استراتژی خود را تنظیم کنید.
- ترکیب روشها : پراکسی مناسب، تقلید رفتار انسانی و مدیریت کوکیها را با هم به کار ببرید.
جمعبندی
برای ساختن یک اسکریپ Playwright که کمتر شناسایی شود، باید همزمان روی چند لایه کار کنید: تنظیمات مرورگر (user-agent، فلگها، WebGL)، پراکسی مناسب و چرخان، و شبیهسازی رفتار انسان. تست مرتب با ابزارهای fingerprinting و پایش لاگ به شما نشان میدهد کدام بخشها نیاز به تقویت دارند. همیشه ملاحظات اخلاقی و حقوقی را در نظر بگیرید و از حمله به زیرساخت سایت یا استخراج دادههای حساس خودداری کنید.
این مقاله حاوی نمونههای کد پایتون برای پیادهسازی عملیِ هر تکنیک بود؛ برای پیادهسازی در پروژههای تولیدی، این قطعات را با لایهٔ مدیریت خطا، لاگینگ و سازوکار احراز هویت یکپارچه کنید.





