从内嵌 JSON 中提取代理 IP 与十六进制端口
解码代理列表脚本调用中已知的 JSON 载荷,并仅在该源格式明确声明时才按十六进制解释端口。
空的 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。
示例中的端口字段明确是十六进制:C38 表示十进制的 3128。不要仅因为两者都叫端口,就把 16 进制套用到其他提供商的十进制字段上。
这是针对所述格式的解析器,不是 JavaScript 解释器。单引号对象字面量、计算值和其他 JavaScript 表达式需要另一套有文档的数据接口。不要为了得到端点列表而执行任意页面代码。
验证源契约,并将协议字段单独保存。如果源改为已填充的 HTML 行,请使用按行提取端点,而不是这个 JavaScript 包装解析器。提取出地址和端口并不能证明该端点当前提供可用的代理服务。