1.77.7: serpPoolPreview SQL 上限 100→2000(修复浏览池清理误判:池>100 时最近使用的温号被误 unwarm)
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/** # 脚本说明
|
||||
* sorry 恢复探测器(在 admin 服务器本机运行,极低负载):每 15 分钟经 serp-api
|
||||
* (runtime=fetch)发 5 个搜索,记录 ok/gate/captcha 比例,写 data/recovery-probe.jsonl,
|
||||
* 全部通过(5/5 ok)时输出 RECOVERED 并退出。用于测量 Google 前缀标记的恢复时间。
|
||||
* nohup env SERP_TOKEN=xxx bun serp-recovery-probe.ts > data/recovery.log 2>&1 &
|
||||
*/
|
||||
import fs from "node:fs";
|
||||
|
||||
/** # 成员变量 基址与令牌(本机) **/
|
||||
const BASE = "http://127.0.0.1:53100";
|
||||
const TOKEN = process.env.SERP_TOKEN ?? "";
|
||||
if (!TOKEN) { console.error("缺少 SERP_TOKEN"); process.exit(1); }
|
||||
/** # 成员变量 输出文件与采样参数 **/
|
||||
const DATA = new URL("./data/", import.meta.url).pathname;
|
||||
fs.mkdirSync(DATA, { recursive: true });
|
||||
const JSONL = `${DATA}recovery-probe.jsonl`;
|
||||
const INTERVAL_MIN = 15;
|
||||
const N = 5;
|
||||
const QUERIES = ["recovery probe coffee maker", "recovery probe running shoes", "recovery probe laptop stand", "recovery probe rice cooker", "recovery probe desk lamp"];
|
||||
|
||||
/** # 函数
|
||||
* 发一个 fetch 出口搜索,分类:ok(200 非门壳)/ gate(x-serp-gate:1)/ captcha(502 CAPTCHA)/ err(其它)。
|
||||
*/
|
||||
async function probe(q: string): Promise<string> {
|
||||
try {
|
||||
const res = await fetch(`${BASE}/api/serp/html/search?q=${encodeURIComponent(q)}&num=10&runtime=fetch`, {
|
||||
headers: { authorization: `Bearer ${TOKEN}` }, signal: AbortSignal.timeout(60000),
|
||||
});
|
||||
if (res.ok) return res.headers.get("x-serp-gate") === "1" ? "gate" : "ok";
|
||||
const j = await res.json().catch(() => null) as any;
|
||||
return j?.code === "CAPTCHA_DETECTED" ? "captcha" : "err";
|
||||
} catch { return "err"; }
|
||||
}
|
||||
|
||||
/** # 主流程:每 15 分钟 5 发(间隔 2s),全 ok 则退出;其它情况最多跑 24h */
|
||||
const started = Date.now();
|
||||
for (;;) {
|
||||
const results: string[] = [];
|
||||
for (let i = 0; i < N; i++) {
|
||||
results.push(await probe(QUERIES[i % QUERIES.length]!));
|
||||
if (i < N - 1) await Bun.sleep(2000);
|
||||
}
|
||||
const ok = results.filter(r => r === "ok").length;
|
||||
const row = { at: new Date().toISOString(), results, ok, gate: results.filter(r => r === "gate").length, captcha: results.filter(r => r === "captcha").length, err: results.filter(r => r === "err").length };
|
||||
fs.appendFileSync(JSONL, JSON.stringify(row) + "\n");
|
||||
console.log(JSON.stringify(row));
|
||||
if (ok === N) { console.log("RECOVERED"); break; }
|
||||
if (Date.now() - started > 24 * 3600_000) { console.log("TIMEOUT 24h"); break; }
|
||||
await Bun.sleep(INTERVAL_MIN * 60_000);
|
||||
}
|
||||
Reference in New Issue
Block a user