

در این مقاله قدمبهقدمِ فنی به روشهای عملی برای «اسکریپ کردن» سایتهایی که از PerimeterX استفاده میکنند میپردازیم. فرض میکنیم خواننده توسعهدهنده پایتون در سطح متوسط است و با مفاهیم پایه Playwright آشنایی دارد. پس از خواندن این مطلب، قادر خواهید بود ترکیبی از پروکسیهای مسکونی، تغییر هدرها، تزریق اسکریپت برای کاهش قابلتشخیص بودن و الگوهای مدیریتی (ریتری، مدیریت سشن، ذخیرهسازی کوکی) را در پروژهی وب اسکریپینگ خود پیادهسازی کنید.
PerimeterX و سرویسهای مشابه از ترکیب مکانیزمهای سمت سرور و سمت کلاینت برای شناسایی رفتارهای غیرعادی استفاده میکنند. مهم است که بدانیم چه چیزهایی معمولاً بررسی میشود تا بتوانیم راهحلهای مناسب طراحی کنیم:
ترکیب روشها معمولاً بهترین نتیجه را میدهد؛ فقط تکیه بر یکی از آنها پایدار نیست. فهرست کلی رویکردها:
# مثال: راهاندازی Playwright با پروکسی و User-Agent (async)
from playwright.async_api import async_playwright
import os
import random
PROXY_SERVER = os.getenv('PROXY_SERVER') # e.g. 'http://residential-proxy.example:8181'
PROXY_USER = os.getenv('PROXY_USER')
PROXY_PASS = os.getenv('PROXY_PASS')
USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1',
]
async def run():
ua = random.choice(USER_AGENTS)
async with async_playwright() as pw:
browser = await pw.chromium.launch(proxy={
'server': PROXY_SERVER,
'username': PROXY_USER,
'password': PROXY_PASS,
}, headless=True)
context = await browser.new_context(user_agent=ua)
page = await context.new_page()
try:
await page.goto('https://www.zillow.com', timeout=120000)
await page.screenshot(path='zillow-proxied.png')
print('screenshot saved')
except Exception as e:
print('navigation failed:', e)
finally:
await browser.close()
# ورودیها: متغیرهای محیطی پروکسی و لیست User-Agent
# خروجی: فایلی به نام zillow-proxied.png در صورت موفقیتتوضیح خطبهخط و نقشها:
# مثال: تزریق JS برای پنهانسازی navigator.webdriver و اصلاح چند ویژگی
from playwright.async_api import async_playwright
import asyncio
INIT_SCRIPT = """
// حذف پرچم webdriver
Object.defineProperty(navigator, 'webdriver', {get: () => false});
// تقلید زبانها
Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
// نمونهای از تعریف fake plugins
Object.defineProperty(navigator, 'plugins', {get: () => [1,2,3]});
"""
async def stealth_example():
async with async_playwright() as pw:
browser = await pw.chromium.launch(headless=False)
context = await browser.new_context()
# اجرای اسکریپت قبل از هر صفحه تا فینگرپرینت کاهش یابد
await context.add_init_script(INIT_SCRIPT)
page = await context.new_page()
await page.goto('https://www.whatismybrowser.com/')
await page.screenshot(path='what-is-stealth.png')
await browser.close()
asyncio.run(stealth_example())توضیحات:
حتماً برای هر درخواست سیاست retry و backoff داشته باشید تا از بلاکهای موقتی و ناپایداری جلوگیری کنید و به سایت فشار نیاورید. نمونه سادهای از الگوی اکسپوننشیال:
import asyncio
async def with_retries(corofn, retries=3):
delay = 1
for i in range(retries):
try:
return await corofn()
except Exception as e:
if i == retries - 1:
raise
await asyncio.sleep(delay)
delay *= 2نکات عملی:
برای سایتهایی مثل Zillow که PerimeterX به کار میگیرد، ترکیب سه مؤلفه زیر معمولاً مؤثر است:
# نمونه ترکیبی: پروکسی + init script + ذخیره کوکی
from playwright.async_api import async_playwright
import os, random, json
PROXY = os.getenv('PROXY_SERVER')
UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
INIT = "Object.defineProperty(navigator, 'webdriver', {get: () => false});"
async def case_study():
async with async_playwright() as pw:
browser = await pw.chromium.launch(proxy={'server': PROXY}, headless=False)
context = await browser.new_context(user_agent=UA)
await context.add_init_script(INIT)
page = await context.new_page()
await page.goto('https://www.zillow.com', timeout=120000)
# ذخیره کوکیها برای اجراهای بعدی
cookies = await context.cookies()
with open('cookies.json', 'w') as f:
json.dump(cookies, f)
await page.screenshot(path='zillow-combined.png')
await browser.close()
# خروجی: اسکرینشات و فایل cookies.jsonتوضیح: این کد ورودیهای محیطی (پروکسی)، User-Agent مشخص، و init script را میگیرد، پس از لود صفحه کوکیها را ذخیره میکند تا در اجراهای بعدی سشن ادامه یابد. این کار به دیدهشدن ترافیک بهعنوان یک کاربر واحد کمک میکند.
برای عبور از PerimeterX دنبالِ «ترکیب» باشید: پروکسی مسکونی (یا موبایل) + هدر و سشن مطابق مرورگر واقعی + اصلاح فینگرپرینت با add_init_script و در نهایت کنترل نرخ درخواست و مدیریت خطا. در پایتون، بهجای تکیه بر بستههای آماده Node مانند puppeteer-extra-plugin-stealth، باید چند تکنیک دستی را ترکیب کنید. همیشه کلیدها و شناسههای حساس را در محیط (env) نگه دارید، و سیاست ریتری/بکآف را برای پایداری پیاده کنید.


