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

برای HTML که برنامه از قبل دریافت کرده است، جدولی که دو ستون نخست آن نشانی IP و پورت است را می‌توان چنین تجزیه کرد:

import ipaddress
from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "html.parser")
table = soup.select_one(table_selector)
if table is None:
    raise ValueError("Expected proxy table was not found")

endpoints = set()
for row in table.select("tbody tr"):
    cells = row.find_all("td", recursive=False)
    if len(cells) < 2:
        continue
    try:
        address = ipaddress.ip_address(cells[0].get_text(strip=True))
        port = int(cells[1].get_text(strip=True))
    except ValueError:
        continue
    if 1 <= port <= 65535:
        endpoints.add((str(address), port))

html و table_selector ورودی‌های برنامه‌اند. انتخابگر و نگاشت ستون‌ها را از نشانه‌گذاری واقعی منبع برگزینید. فهرست پروکسی رایگان یکی از منابع رکوردهای نقطه پایانی است، اما پیش از برگزیدن آن نگاشت باید سطرهایش بررسی شود. نه شناسه تاریخی جدول و نه این ادعا که یک صفحه دقیقاً 300 رکورد دارد، طرحی پایدار نیست.

این مجموعه جفت‌های تکراری نشانی و پورت را حذف می‌کند و در همان حال پیوند هر جفت را حفظ می‌کند. با این حال واردسازی غیرمنتظره با نتیجه صفر باید بررسی شود: ممکن است جدول تغییر کرده باشد یا سند دریافت‌شده به‌جای فهرست، صفحه چالش باشد.

اگر مهم باشند، هر پروتکل اعلام‌شده و فیلدهای زمان بررسی را همراه نقطه پایانی نگه دارید. استخراج یک IP و پورت باورپذیر فقط قالب را ثابت می‌کند، نه اینکه نقطه پایانی اکنون سرویس HTTP یا SOCKS کارآمدی ارائه دهد.

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

مقالات مرتبط