API — 端口池
打开并管理端口池——从代理列表批量打开的端口,用于大规模并发任务——然后导出结果。
打开端口池
/api/v1/scraper/tasks需要鉴权从代理列表打开一个端口池。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 端口池名称。 |
source | object | 是 | 代理列表的来源:kind 为 "file"、"url" 或 "inline";location 为路径或链接;"inline" 时由 content 直接承载列表。可选的 refresh_interval 用于重新读取来源,其值为纳秒整数:10 分钟为 600000000000,1 分钟为 60000000000,30 秒为 30000000000。默认 10 分钟;小于 30 秒的值会被静默提升为 30 秒,且响应中不会给出任何提示——直接填 600 表示 600 纳秒,来源(包括外部 URL)将每 30 秒被重新读取一次。default_scheme 适用于不带协议的 host:port 条目(默认 socks5)。 |
target | int | 是 | 端口池需要开启的端口数量。 |
port_lo | int | 否 | 端口池可使用的本地端口范围下限。 |
port_hi | int | 否 | 端口范围上限。 |
protocol | string | 否 | 池中端口的监听协议:"socks5"(默认)或 "http"。 |
up_policy | object | 否 | 端口更换出口代理的频率。mode 可为 "requests"(每 n 个连接)、"minutes"(每 n 分钟)或 "on_error"(保持代理不变,直到客户端收到错误响应)。默认每个请求更换一次。🔴 当 js_solver: true 时该频率不生效:up_policy 与 fp_policy 都会被强制改为“无频率”。端口在第一个连接上取得出口代理,并连同身份一直保持到端口关闭;出口只在连接出错后被临时更换(此时身份不变)。唯一的例外是 mode: on_error,它不受该强制影响,按上文所述工作。 |
fp_policy | object | 否 | 端口更换身份的频率,结构与上述三种模式相同。默认每 10 个请求更换一次。🔴 当 js_solver: true 时同样被强制,参见上方 up_policy:端口身份完全不按频率轮换——on_error 模式除外。 |
device | string | 否 | 池内身份使用的浏览器类型,例如 "chrome"。可用组合见 GET /api/v1/scraper/device_matrix。 |
device_os | string | 否 | 池内身份使用的操作系统,例如 "windows"。 |
profile_source | string | 否 | 身份来源:"auto" 表示实时生成,"db" 表示取自精选数据库。 |
auto_ua | bool | 否 | 按请求的 User-Agent 选择身份,而非使用端口池设置。 |
spoof_headers | bool | 否 | 将外发请求头改写为与当前浏览器一致。建议采集场景开启,默认已开启。 |
connect_timeout_seconds | int | 否 | 池中每个端口单次连接尝试的上限(秒)。默认 5。 |
request_timeout_seconds | int | 否 | 池中每个端口的静默预算(秒):包含重试的连接阶段,以及随后等待首字节的时间。默认 30,设为 0 则取消限制。 |
idle_timeout_sec | int | 否 | 池中端口连接的空闲超时(秒):若在此时长内没有字节传输,连接将被关闭。默认 60。请勿与 idle_seconds 混淆,后者关闭的是端口本身。读取由早期版本保存的端口池时,仍接受旧名称 request_timeout_sec。 |
idle_seconds | int | 否 | 端口存活时长(秒)。端口池默认保持其端口开启(0)。 |
curl -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"tiktok-pool","target":100,"port_lo":20000,"port_hi":30000,
"protocol":"socks5",
"source":{"kind":"file","location":"C:/proxies.txt"},
"up_policy":{"mode":"requests","n":1},
"fp_policy":{"mode":"requests","n":10},
"connect_timeout_seconds":5,"request_timeout_seconds":30}' \
http://127.0.0.1:8891/api/v1/scraper/tasks{
"id": "pool-7f3a",
"export_token": "3b91c0d4e5f6",
"warnings": null
}
🔴 id 与 export_token 来自此处:id 用于 /scraper/tasks/{id}/…,export_token 用于导出地址 /export/{token}/proxies.txt。除 GET /api/v1/scraper/tasks 外没有其他地方可以看到它们。warnings 只包含一条提示——当实际打开的端口少于请求的 target 时的“opened N of M ports (range LO-HI too small or ports busy)”;若全部打开,该字段返回 null。它不会报告代理源的任何情况:既不会给出未能解析的条目数,也不会告知源根本没有读取成功(URL 返回 404 或超时、文件缺失)。此时池仍会启动——出口列表为空——并返回 200,只能通过流量失败才能察觉。请事先使用单独的 POST /api/v1/scraper/probe 检查源:它会返回 total(可用条目数)与 bad(损坏条目数)。
在 Lite 套餐上返回 403 “the scraper port pool requires a Pro license (single-thread Lite cannot open a port pool)”;若该构建未接入端口池,返回 503 “scraper manager not configured”;若配置不自洽(port_lo 大于 port_hi、target 小于 1,或 profile_source、up_policy.mode、fp_policy.mode、vdns_mode 取值未知,或 device 与 device_os 未知/互不兼容),返回 400 并附说明。🔴 端口区间不足以容纳 target 并不是拒绝:端口池会打开能放下的端口——若全部被占用则一个也不打开——仍返回 200,并在 warnings 中给出形如 “opened 11 of 100 ports (range 20000-20010 too small or ports busy)” 的说明。因此不要只看状态码,请检查 warnings。
有两个默认值是在创建时应用的,而不是保存在配置里:未设置时 protocol 变为 socks5(以便 UDP 与 HTTP/3 可用),vdns_mode 变为 forced——目标名称在出口侧解析,不会泄漏到您所在网络的 DNS。显式设置的 "off" 仍表示关闭。
池端口的高级设置
端口池自行打开其端口,因此未传达到它的设置会保持默认值——而表单看上去却像已生效。下列字段会应用到池中的每个端口。
| 字段 | 类型 | 作用 |
|---|---|---|
js_solver | bool | 在每个池端口上启用 Challenge Breaker:遇到验证的请求会转入解题池。需要拆解 TLS——与 tls_passthrough 不兼容。🔴 它会让端口变为固定:池的 up_policy 与 fp_policy 不再按频率生效——每个端口在其整个生命周期内只用一个出口 IP 和一个身份(例外:on_error 模式,以及连接出错后的临时换出口)。这是有意为之:破解验证所获得的会话与“出口 + 指纹”这一组合绑定,会话进行中更换其中任何一项都会使其作废。出口的多样性来自池中端口的数量,而不是轮换频率——请提高 target 并扩大端口范围。该替换在 API 上看不出来:GET /api/v1/scraper/tasks/{id}/config 仍会返回您原本提交的 up_policy 与 fp_policy,因为强制只作用于运行中的端口,而不改动已保存的配置。 |
captcha_action | string | 遇到验证码(而非无人值守型验证)时的处理方式:rotate_retry(默认)更换身份并重试;return_to_script 把该验证交回您的代码。 |
captcha_max_attempts | int | 在 rotate_retry 下最多以新身份重试多少次。默认 3 次。 |
keep_sessions | bool | 每个池端口维护自己的按域名 Cookie 罐:吸收 Set-Cookie、注入 Cookie 并跟随重定向。与 js_solver 无关。 |
cache_mode | string | 池端口上的缓存模式:normal、hard、hard-media 或 hard-autowarm。 |
cache_ignore_no_cache | bool | 忽略 no-cache 头进行缓存。 |
vdns_mode | string | 虚拟 DNS:off、on_leak 或 forced。🔴 对于新建的池,若未设置该字段则为 forced——目标名称在出口侧解析,不会泄漏到您所在网络的 DNS。 |
leak_guard | string | 池端口启动前的泄漏检查:off、warn 或 enforce。 |
force_ipv4 | bool | 仅通过 IPv4 出口。 |
tls_passthrough | bool | TLS 原样透传。此时池端口上的缓存、日志与 Challenge Breaker 都不起作用:内容不被读取。 |
tls_mirror | bool | 对外重放客户端自身的已采集指纹,而不是配置文件中的指纹。 |
h2_spoofing | bool | 把 HTTP/2 设置伪装为浏览器配置文件的形态。 |
spoof_user_agent | bool | 伪装 User-Agent。关闭时逐字节转发您的客户端自身的请求头。 |
enable_http3 | bool | 当站点提供 h3 时改用 HTTP/3 重新发起连接。 |
upstream_tls_insecure | bool | 对 https 代理关闭证书校验。仅适用于使用自签名证书的自有代理。 |
allow_mitm_upstream | bool | 允许自行拆解 TLS 的出口。默认禁止:此类出口会抹掉指纹。 |
max_concurrent | int | 每个池端口的并发请求上限;0 表示不限。 |
sem_timeout | int | 请求在该上限内等待空位的秒数。 |
skip_retry | bool | 网络错误后不重试请求。 |
retry_delay_ms | int | 重试之间的间隔(毫秒)。 |
列出与停止端口池
/api/v1/scraper/tasks需要鉴权所有端口池的快照:已打开多少端口、具体是哪些端口,以及它们所在的端口范围。
curl -H "X-API-Key: YOUR_API_KEY" \
http://127.0.0.1:8891/api/v1/scraper/tasks[
{
"id": "pool-7f3a",
"name": "catalogue-pool",
"target": 100,
"ports_up": 98,
"ports": [20000, 20001, 20002],
"export_token": "3b91c0d4e5f6",
"port_lo": 20000,
"port_hi": 30000
}
]- 空数组表示当前没有任何端口池——这不是错误。若该构建未接入端口池,返回 503 “scraper manager not configured”。
- 响应中不含源代理数量,也不含轮换状态:源中有多少条目由 POST /api/v1/scraper/probe 给出(total 字段),配置了何种轮换由 GET /api/v1/scraper/tasks/{id}/config 给出(up_policy 与 fp_policy)。ports_up 是已开启端口的数量,ports 则是这些端口的编号。
/api/v1/scraper/tasks/{id}需要鉴权停止端口池并关闭其全部端口。经由它们的流量会被切断。
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" \
http://127.0.0.1:8891/api/v1/scraper/tasks/pool-7f3a{
"ok": true
}- 若不存在该 id 的端口池,返回 404 并附管理器文本。
/api/v1/scraper/tasks/{id}/test需要鉴权在端口池的某个运行端口上执行完整的端口测试——与 POST /api/v1/port/{port}/test 相同——并返回被测试的端口。
curl -X POST -H "X-API-Key: YOUR_API_KEY" \
http://127.0.0.1:8891/api/v1/scraper/tasks/pool-7f3a/test{
"port": 20134,
"report": { "leak": { "…": "…" }, "fingerprint": { "match": true },
"udp": { "supported": true }, "ok": true }
}- 在端口池尚未启动任何端口时返回 409 “scraper task has no open ports yet”;端口已不再工作时返回 409 “scraper task ports are not live”。若端口池不存在,返回 404。
/api/v1/scraper/tasks/{id}/config需要鉴权以 POST /api/v1/scraper/tasks 所接受的完全相同形态返回端口池的已保存配置:修改的方式是先停止再重新启动。
curl -H "X-API-Key: YOUR_API_KEY" \
http://127.0.0.1:8891/api/v1/scraper/tasks/pool-7f3a/config{
"id": "pool-7f3a",
"name": "catalogue-pool",
"port_lo": 20000,
"port_hi": 30000,
"target": 100,
"protocol": "socks5",
"source": { "kind": "file", "location": "C:/proxies.txt" },
"up_policy": { "mode": "requests", "n": 1 },
"fp_policy": { "mode": "requests", "n": 10 },
"vdns_mode": "forced",
"export_token": "3b91c0d4e5f6"
}- 404 “task not found”。该配置还包含打开表中未列出的高级字段:cache_mode、leak_guard、js_solver、keep_sessions、captcha_action 以及端口的三个超时。
/api/v1/scraper/device_matrix需要鉴权列出可用于构建端口池的浏览器与操作系统组合。
curl -H "X-API-Key: YOUR_API_KEY" \
http://127.0.0.1:8891/api/v1/scraper/device_matrix{
"chrome": ["windows", "macos", "linux", "android", "ios"],
"edge": ["windows", "macos", "linux", "android", "ios"],
"firefox": ["windows", "macos", "linux", "android", "ios"],
"safari": ["macos", "ios"]
}- 此处的取值用于打开端口池时的 device 与 device_os 字段。
- 唯一不可能的组合是非 Apple 设备上的 Safari。该表描述的是显式指定时校验器所接受的范围;device: random 取自更窄的集合——Chrome、Firefox、Edge 不含 iOS,Firefox、Edge 不含 Android——这些组合只能显式指定。
/api/v1/scraper/probe需要鉴权下载并解析代理源,但不启动端口池:可用条目数、损坏条目数、出现了哪些协议,以及供您自行测试连通性的随机样本。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
source | object | 是 | 与打开端口池时相同的源对象:kind(file、url 或 inline)、location 与 content。 |
{ "source": { "kind": "url", "location": "https://example.com/proxies.txt" } }curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"source":{"kind":"url","location":"https://example.com/proxies.txt"}}' \
http://127.0.0.1:8891/api/v1/scraper/probe{
"total": 13045,
"bad": 210,
"by_scheme": { "socks5": 12835, "http": 210 },
"sample": ["socks5://203.0.113.10:1080", "socks5://203.0.113.11:1080"]
}- 若源无法下载或解析,返回 400 并附说明。请求体上限为 32 MiB——即整份粘贴列表的大小;探测上限为 35 秒。
- 许可未激活时返回 403:与其他出口检查一样,该接口位于许可之后。
导出结果
/export/{token}/proxies.txt无需鉴权将端口池的端口下载为纯文本代理列表。访问权限由 URL 中的令牌授予,因此无需 API 密钥。
curl http://127.0.0.1:8891/export/TASK_TOKEN/proxies.txt