プロキシの各行を1つの単位として解析します。ページ全体で一致するtdをすべて平坦化し、結果を固定個数でまとめると、セルが欠けたり別のテーブルが現れたりしたときに、ある行のアドレスが次の行のポートと組み合わされることがあります。

アプリケーションがすでに取得したHTMLについては、最初の2列が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はアプリケーションの入力です。セレクタと列の対応付けは、取得元の実際のマークアップから選んでください。無料プロキシ一覧は端点レコードの情報源の一つですが、その対応付けを選ぶ前に、その行を確認すべきです。過去のテーブルIDも、ページにちょうど300件のレコードがあるという主張も、永続するスキーマではありません。

集合はアドレスとポートの重複した組を除去しつつ、各組の対応関係を保持します。予期しない0件の取り込みは依然として調査すべきです。テーブルが変わったか、取得した文書が一覧ではなくチャレンジページである可能性があります。

意味がある場合は、公表されているプロトコルと検査時刻の項目を端点と一緒に保持してください。もっともらしいIPとポートを抽出することは形式を示すだけで、その端点が現在動作するHTTPまたはSOCKSサービスを提供していることを示すものではありません。

ヘッダー行やフィルター行は端点ではありません。thセルだけを含む行はスキップされ、空の項目やアドレスでない項目は検証に失敗します。先頭行と最終行を位置で捨てないでください。ページのレイアウトが変われば、どちらも実際の端点になり得ます。

関連記事