빈 HTML 표가 항상 응답에 프록시 레코드가 없다는 뜻은 아닙니다. 일부 목록은 JSON 객체를 JavaScript 호출 안에 넣고 나중에 행을 채웁니다.

이미 가져온 소스가 특정 래퍼 gp.insertPrx 뒤에 JSON 객체를 사용하는 경우:

import ipaddress
import json
import re

decoder = json.JSONDecoder()
endpoints = set()
for marker in re.finditer(r"gp[.]insertPrx\(\s*", html):
    try:
        row, end = decoder.raw_decode(html, marker.end())
        if not isinstance(row, dict):
            continue
        address = ipaddress.ip_address(row["PROXY_IP"])
        port = int(row["PROXY_PORT"], 16)
    except (ValueError, KeyError, TypeError):
        continue
    if 1 <= port <= 65535 and html[end:].lstrip().startswith(");"):
        endpoints.add((str(address), port))

html은 브라우저 객체가 아니라 소스 텍스트입니다. 정규식은 알려진 래퍼를 찾고, JSONDecoder는 JSON 값이 끝나는 위치를 판단합니다. 이렇게 하면 중첩된 JSON을 정규식만으로 파싱하려는 시도를 피할 수 있습니다.

예제의 포트 필드는 명시적으로 16진수입니다. C38은 10진수 3128을 뜻합니다. 둘 다 포트라고 불린다는 이유만으로 다른 제공자의 10진 필드에 16진법을 적용하지 마세요.

이것은 명시된 형식을 위한 파서이지 JavaScript 인터프리터가 아닙니다. 작은따옴표 객체 리터럴, 계산된 값, 기타 JavaScript 표현식에는 다른 문서화된 데이터 인터페이스가 필요합니다. 엔드포인트 목록을 얻기 위해 임의의 페이지 코드를 실행하지 마세요.

소스 계약을 검증하고 프로토콜 필드는 따로 보관하세요. 대신 HTML 행이 채워진 소스라면 이 JavaScript 래퍼 파서 대신 행 단위 엔드포인트 추출을 사용하세요. 주소와 포트를 추출해도 해당 엔드포인트가 현재 사용 가능한 프록시 서비스를 제공한다는 것은 아닙니다.

관련 글