Skip to content
Advanced / 3 min read

چگونه یک چرخانندهٔ پروکسی ردیاب رتبه با پروکسی‌های مسکونی IPRoyal و Python بسازیم

یک راهنمای کد-محور برای مسیریابی یک ردیاب رتبه Python از طریق پروکسی‌های SOCKS5 مسکونی IPRoyal، همراه با هدف‌گیری کشوری، نشست‌های چسبنده، محدودیت‌های هم‌زمانی، و مدیریت تلاش مجدد برای بررسی‌های قابل‌اعتماد SERP به تفکیک کشور.

SOCKS5 HTTP(S) وب اسکرپینگ پایش سئو

مرور کلی

ردیاب‌های رتبه یک کار را بارها و بارها انجام می‌دهند: جست‌وجو در یک موتور جست‌وجو از یک مکان مشخص و ثبت اینکه یک دامنه کجا ظاهر می‌شود. این الگو بدون پروکسی خیلی زود می‌شکند. موتورهای جست‌وجو نتایج را بر اساس IP درخواست‌کننده بومی‌سازی می‌کنند و IPهایی را که با حجم بالا از آن‌ها جست‌وجو می‌کنند، محدود یا مسدود می‌کنند.

این آموزش نشان می‌دهد چگونه یک ردیاب رتبه Python را از طریق پروکسی‌های مسکونی IPRoyal روی SOCKS5 اجرا کنید: URL پروکسی را بسازید، وقتی به صفحه‌بندی نیاز دارید نشست‌ها را چسبنده نگه دارید، وقتی نیاز ندارید بچرخانید، و خرابی‌هایی را که واقعاً در محیط عملیاتی می‌بینید مدیریت کنید.

IPRoyal پروکسی‌های مسکونی، ISP و دیتاسنتری را روی HTTP، SOCKS5 و تونل‌سازی به سبک Shadowsocks ارائه می‌دهد، از یک استخر ۳۲ میلیون+ IP تبلیغ می‌کند، و ترافیک مسکونی را به‌صورت پرداخت به‌ازای مصرف با طرح‌های ماهانه ثابت در برخی محصولات صورت‌حساب می‌کند. میزبان، پورت، نام کاربری و رمز عبور گیت‌وی در داشبورد IPRoyal شما قرار دارند.

کدام نوع پروکسی برای ردیابی رتبه مناسب است؟

نوع پروکسی بهترین برای ردیابی رتبه بده‌بستان
مسکونی (چرخشی) SERPهای سطح کشور و شهر؛ استخر بزرگ ۳۲ میلیون+ حجم درخواست را پخش می‌کند پاسخ‌های کندتر؛ IP خروجی بین درخواست‌ها تغییر می‌کند
ISP (مسکونی ثابت) بررسی‌های تکرارپذیر از همان آدرس ردپای مکانی کوچک‌تر از مسکونی
دیتاسنتر کار سبک و پرحجم که اسکرپینگ SERP نیست سریع و کم‌هزینه، اما به‌راحتی توسط موتورهای جست‌وجو انگشت‌نگاری می‌شود

چرخش در مقابل نشست‌های چسبنده

  • وقتی فقط به یک صفحه نتیجه برای هر کلمه کلیدی نیاز دارید، هر درخواست را بچرخانید.
  • وقتی صفحه‌بندی را دنبال می‌کنید، بلوک‌های پرسش‌های مرتبط را باز می‌کنید، یا برای دنباله‌ای از درخواست‌ها به همان IP خروجی نیاز دارید، یک نشست چسبنده نگه دارید (از چند دقیقه تا حدوداً ۳۰ دقیقه).
  • کشوری را هدف بگیرید که با locale مورد گزارش شما مطابقت دارد. یک بررسی رتبه de-DE از طریق IP خروجی آمریکا، بررسی رتبه آلمانی نیست.

هدف‌گیری نشست و کشور از طریق نام کاربری پروکسی یا زیردامنه گیت‌وی کنترل می‌شود. الگوی دقیق را از داشبورد IPRoyal خود کپی کنید و حدس نزنید؛ کد زیر از جای‌نگهدارهای پرکاربرد -session- و -country- استفاده می‌کند.

پیش‌نیازها

  • Python 3.9 یا جدیدتر
  • افزونه‌های SOCKS برای Requests: pip install "requests[socks]"
  • میزبان، پورت، نام کاربری و رمز عبور گیت‌وی IPRoyal از داشبورد شما
  • یک فایل کلمات کلیدی با یک ردیف برای هر کلمه کلیدی: query، کد کشور و locale

مراحل

۱. اعتبارنامه‌های خود را export کنید تا هرگز در فایل منبع قرار نگیرند.

export IPROYAL_HOST="gateway-host-from-dashboard"
export IPROYAL_PORT="gateway-port-from-dashboard"
export IPROYAL_USER="your-username"
export IPROYAL_PASS="your-password"

در Windows PowerShell، به‌جای آن از $env:IPROYAL_HOST = "..." استفاده کنید.

۲. برای هر درخواست یک URL پروکسی بسازید، با هدف‌گیری اختیاری کشور و نشست. از طرح socks5h استفاده کنید تا DNS در پروکسی حل شود، نه روی دستگاه شما.

import os
import random
import string
import time

import requests

PROXY_HOST = os.environ['IPROYAL_HOST']
PROXY_PORT = os.environ['IPROYAL_PORT']
PROXY_USER = os.environ['IPROYAL_USER']
PROXY_PASS = os.environ['IPROYAL_PASS']

LOCALE_HEADERS = {
    'en-US': {'Accept-Language': 'en-US,en;q=0.9'},
    'de-DE': {'Accept-Language': 'de-DE,de;q=0.9'},
    'ja-JP': {'Accept-Language': 'ja-JP,ja;q=0.9'},
}


def new_session_id() -> str:
    """Short, unique token used to pin a sticky session."""
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))


def proxy_url(country: str, session_id: str | None = None) -> str:
    user = PROXY_USER
    if session_id:
        user = f'{user}-session-{session_id}'
    if country:
        user = f'{user}-country-{country.lower()}'
    return f'socks5h://{user}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}'

۳. درخواست را در تلاش‌های مجدد با عقب‌نشینی نمایی بپیچید. یک بررسی ناموفق نباید یک اجرای ۲۰۰۰ کلمه کلیدی را متوقف کند.

def fetch_serp(query: str, country: str, locale: str,
               session_id: str | None = None, attempts: int = 3) -> str | None:
    proxy = proxy_url(country, session_id)
    proxies = {'http': proxy, 'https': proxy}
    headers = {
        'User-Agent': 'Mozilla/5.0 (compatible; RankTracker/1.0)',
        **LOCALE_HEADERS.get(locale, {}),
    }

    for attempt in range(1, attempts + 1):
        try:
            response = requests.get(
                'https://your-permitted-search-endpoint/search',
                params={'q': query, 'hl': locale},
                proxies=proxies,
                headers=headers,
                timeout=30,
            )
            response.raise_for_status()
            return response.text
        except requests.RequestException as exc:
            print(f'attempt {attempt} failed for {query!r}: {exc}')
            time.sleep(2 ** attempt)

    return None

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

۴. برای هر کلمه کلیدی یک نشست چسبنده اختصاص دهید تا صفحه‌بندی و درخواست‌های پیگیری از همان IP خروجی دوباره استفاده کنند.

def check_keyword(row: dict) -> dict:
    session_id = new_session_id()
    html = fetch_serp(row['query'], row['country'], row['locale'], session_id=session_id)
    return {
        'query': row['query'],
        'country': row['country'],
        'position': rank_position(html, row['domain']) if html else None,
        'status': 'ok' if html else 'failed',
    }

۵. موقعیت‌ها را با همان پارسر/تجزیه‌کننده‌ای که از قبل استفاده می‌کنید استخراج کنید.

def rank_position(html: str | None, domain: str) -> int | None:
    if not html:
        return None
    # Parse with lxml, selectolax, or BeautifulSoup, match result URLs
    # against `domain`, and return the 1-based index of the first match.
    ...

۶. هم‌زمانی را محدود کنید. استخرهای مسکونی بزرگ‌اند اما نامحدود نیستند، و کوبیدن یک endpoint از بسیاری از IPها به‌طور هم‌زمان سریع‌ترین مسیر به مسدود شدن است.

from concurrent.futures import ThreadPoolExecutor


def run_batch(keywords: list[dict], workers: int = 8) -> list[dict]:
    with ThreadPoolExecutor(max_workers=workers) as pool:
        return list(pool.map(check_keyword, keywords))
  • با ۵-۸ worker شروع کنید و عدد را فقط تا زمانی افزایش دهید که نرخ موفقیت شما بالای حدود ۹۵٪ باقی بماند.
  • بین تلاش‌های مجدد یک jitter تصادفی کوچک اضافه کنید تا تلاش‌های مجدد هم‌زمان/هماهنگ نرسند.

۷. HTML خام را برای یک بازه کوتاه ذخیره کنید تا بتوانید تاریخچه را بدون اسکرپینگ دوباره تجزیه کنید.

import json
from pathlib import Path


def save_result(result: dict) -> None:
    out = Path('rank-results')
    out.mkdir(exist_ok=True)
    name = result['query'][:40].replace('/', '_')
    with (out / f'{name}.json').open('w', encoding='utf-8') as handle:
        json.dump(result, handle, ensure_ascii=False)

۸. اجرا را زمان‌بندی کنید و ثبت کنید که کدام پیکربندی پروکسی هر نتیجه را تولید کرده است. وقتی یک رتبه تغییر می‌کند، می‌خواهید بدانید SERP جابه‌جا شده یا پروکسی.

# Example cron entry: run the tracker at 06:00 and 18:00 local time
0 6,18 * * * cd /srv/rank-tracker && /usr/bin/python3 track.py >> logs/rank.log 2>&1

عیب‌یابی

  • 407 Proxy Authentication Required: نام کاربری یا رمز عبور اشتباه است، یا یک کاراکتر خاص در رمز عبور encode نشده است. قبل از قرار دادن رمز عبور در URL، @، :، / و # را percent-encode کنید.
  • Missing dependencies for SOCKS support: Requests به افزونه SOCKS نیاز دارد. pip install "requests[socks]" را در همان محیط مجازی اسکریپت خود اجرا کنید.
  • نتایج کشور اشتباه را نشان می‌دهند: هدف‌گیری کشور بخشی از نام کاربری پروکسی است. برای یک کلمه کلیدی proxy_url(...) را چاپ کنید و تأیید کنید کد کشور مورد انتظار ظاهر می‌شود، قبل از اینکه موتور جست‌وجو را سرزنش کنید.
  • هر درخواست از همان IP استفاده می‌کند: شما دارید یک session ID را دوباره استفاده می‌کنید. مؤلفه session را حذف کنید تا ارائه‌دهنده بچرخاند.
  • یک کشور به‌طور ناگهانی مسدود می‌شود: هم‌زمانی را برای آن کشور کاهش دهید، تهاجمی‌تر بچرخانید، و بررسی کنید آیا endpoint شروع به بازگرداندن صفحات رضایت یا کپچا به‌جای نتایج کرده است.
  • کندتر از حد انتظار: مسیریابی مسکونی تأخیر اضافه می‌کند. برای پروکسی‌های مسکونی یا ISP تایم‌اوت را به ۳۰-۴۵ ثانیه افزایش دهید و پروکسی‌های دیتاسنتر را برای کارهای غیر-SERP نگه دارید.

خلاصه

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