tt-help-cli-ycl 1.4.47 → 1.4.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tt-help-cli-ycl",
3
- "version": "1.4.47",
3
+ "version": "1.4.49",
4
4
  "description": "TikTok user & video data scraper - extract ttSeller, verified, locationCreated from HTML source",
5
5
  "type": "module",
6
6
  "bin": {
@@ -83,135 +83,58 @@ function extractJsonByKey(html, keyPattern) {
83
83
 
84
84
  /**
85
85
  * Windows: 后台服务的 Playwright 浏览器在 Session 0(隔离桌面),
86
- * RDP 看不到。找到交互桌面 Session,用计划任务推到那个 Session。
87
- * 配置环境变量(可选):
88
- * CAPTCHA_RECOVERY_USER - schtasks /ru 用户名(必需,否则无法跨 Session)
89
- * CAPTCHA_RECOVERY_PASS - schtasks /rp 密码
86
+ * RDP 看不到。改为用 start 命令推到交互桌面,然后轮询 undici 等 IP 恢复信用。
90
87
  */
91
- let winRecoveryRunning = false;
92
-
93
88
  async function resolveCaptchaWindows(url, proxyUrl) {
94
- if (winRecoveryRunning) {
95
- console.error("[shop-scraper] Windows: 验证码恢复已在运行,跳过");
96
- return false;
89
+ // 用 Windows start 命令在交互桌面打开 Edge
90
+ const edgeUrl = url.replace("shop.tiktok.com", "www.tiktok.com/shop/pdp");
91
+ try {
92
+ execSync(`start "" "microsoft-edge:${edgeUrl}"`, {
93
+ shell: "cmd.exe",
94
+ timeout: 5000,
95
+ });
96
+ console.error(
97
+ "[shop-scraper] Windows: 已用 start 命令在交互桌面打开 Edge,请在 RDP 中完成验证码",
98
+ );
99
+ } catch (e) {
100
+ console.error("[shop-scraper] Windows: start 命令失败:", e.message);
97
101
  }
98
- winRecoveryRunning = true;
99
102
 
100
- try {
101
- const edgeUrl = url.replace("shop.tiktok.com", "www.tiktok.com/shop/pdp");
102
- const taskName = "TikTokCaptchaRecovery";
103
+ // 轮询 undici 等待 IP 信用恢复(用户解完验证码后代理 IP 就有信用了)
104
+ const proxy = proxyUrl || DEFAULT_PROXY;
105
+ const agent = proxy ? new ProxyAgent(proxy) : null;
106
+ const POLL_MS = 5000;
107
+ const MAX_WAIT_MS = 3600_000; // 最长等 1 小时
108
+ const start = Date.now();
103
109
 
104
- // 1. 找到 RDP 交互桌面 Session(Active 且非 Session 0)
105
- let sessionId = null;
110
+ while (Date.now() - start < MAX_WAIT_MS) {
111
+ await new Promise((r) => setTimeout(r, POLL_MS));
106
112
  try {
107
- const sessions = execSync(
108
- `powershell -NoProfile -Command "query session 2>$null | findstr Active"`,
109
- { shell: "cmd.exe", timeout: 5000, encoding: "utf-8" },
110
- );
111
- const lines = sessions.trim().split("\n");
112
- for (const line of lines) {
113
- // 匹配 RDP 会话: ">rdp-tcp#1 username 2 Active"
114
- const match = line.match(/\s(\d+)\s+Active/);
115
- if (match && match[1] !== "0") {
116
- sessionId = parseInt(match[1], 10);
117
- break;
118
- }
113
+ const { body } = await request(url, {
114
+ headers: PDP_HEADERS,
115
+ ...(agent ? { dispatcher: agent } : {}),
116
+ });
117
+ const html = await body.text();
118
+ if (
119
+ html.includes('"product_model"') ||
120
+ html.includes('"review_ratings"')
121
+ ) {
122
+ console.error("[shop-scraper] Captcha solved, IP credit restored");
123
+ return true;
119
124
  }
120
125
  } catch {
121
- console.error("[shop-scraper] Windows: 无法获取交互 Session");
126
+ // 继续轮询
122
127
  }
123
-
124
- if (sessionId) {
128
+ // 每 60 秒打印一次状态
129
+ if (Math.round((Date.now() - start) / 60000) % 5 === 0) {
125
130
  console.error(
126
- `[shop-scraper] Windows: Session ${sessionId},用计划任务启动 Edge`,
131
+ `[shop-scraper] 等待验证码解决中... 已等待 ${Math.round((Date.now() - start) / 60000)} 分钟`,
127
132
  );
128
- // 清理旧任务
129
- try {
130
- execSync(`schtasks /delete /tn "${taskName}" /f 2>$null`, {
131
- shell: "cmd.exe",
132
- });
133
- } catch {}
134
-
135
- const taskUser = process.env.CAPTCHA_RECOVERY_USER || "";
136
- const taskPass = process.env.CAPTCHA_RECOVERY_PASS || "";
137
-
138
- if (taskUser && taskPass) {
139
- // 跨 Session:指定用户 + 交互模式
140
- const today = new Date().toISOString().slice(0, 10).replace(/-/g, "/");
141
- execSync(
142
- `schtasks /create /tn "${taskName}" /tr "msedge \\"${edgeUrl}\\"" /sc once /sd ${today} /st 00:00 /ru "${taskUser}" /rp "${taskPass}" /it /f`,
143
- { shell: "cmd.exe", timeout: 10000 },
144
- );
145
- } else {
146
- // 回退:无凭证时只能当前 Session(如果 webserver 从 RDP 启动才能看到)
147
- console.error(
148
- "[shop-scraper] Windows: 未设置 CAPTCHA_RECOVERY_USER/PASS,计划任务仅限当前 Session",
149
- );
150
- execSync(
151
- `schtasks /create /tn "${taskName}" /tr "msedge \\"${edgeUrl}\\"" /sc once /st 00:00 /it /f`,
152
- { shell: "cmd.exe", timeout: 10000 },
153
- );
154
- }
155
-
156
- execSync(`schtasks /run /tn "${taskName}"`, {
157
- shell: "cmd.exe",
158
- timeout: 10000,
159
- });
160
- setTimeout(() => {
161
- try {
162
- execSync(`schtasks /delete /tn "${taskName}" /f 2>$null`, {
163
- shell: "cmd.exe",
164
- });
165
- } catch {}
166
- }, 10000);
167
- } else {
168
- console.error(
169
- "[shop-scraper] Windows: 未找到交互 Session,尝试直接 start",
170
- );
171
- try {
172
- execSync(`start "" "microsoft-edge:${edgeUrl}"`, {
173
- shell: "cmd.exe",
174
- timeout: 5000,
175
- });
176
- } catch {}
177
133
  }
178
-
179
- // 2. 轮询 undici 等待 IP 信用恢复
180
- const proxy = proxyUrl || DEFAULT_PROXY;
181
- const agent = proxy ? new ProxyAgent(proxy) : null;
182
- const POLL_MS = 5000;
183
- const MAX_WAIT_MS = 3600_000;
184
- const startTime = Date.now();
185
-
186
- while (Date.now() - startTime < MAX_WAIT_MS) {
187
- await new Promise((r) => setTimeout(r, POLL_MS));
188
- try {
189
- const { body } = await request(url, {
190
- headers: PDP_HEADERS,
191
- ...(agent ? { dispatcher: agent } : {}),
192
- });
193
- const html = await body.text();
194
- if (
195
- html.includes('"product_model"') ||
196
- html.includes('"review_ratings"')
197
- ) {
198
- console.error("[shop-scraper] Captcha solved, IP credit restored");
199
- return true;
200
- }
201
- } catch {}
202
- const waited = Math.round((Date.now() - startTime) / 60000);
203
- if (waited > 0 && waited % 5 === 0) {
204
- console.error(
205
- `[shop-scraper] 等待验证码解决中... 已等待 ${waited} 分钟`,
206
- );
207
- }
208
- }
209
-
210
- console.error("[shop-scraper] Windows: 等待验证码超时");
211
- return false;
212
- } finally {
213
- winRecoveryRunning = false;
214
134
  }
135
+
136
+ console.error("[shop-scraper] Windows: 等待验证码超时");
137
+ return false;
215
138
  }
216
139
 
217
140
  /**