tt-help-cli-ycl 1.3.49 → 1.3.50

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.3.49",
3
+ "version": "1.3.50",
4
4
  "description": "TikTok user & video data scraper - extract ttSeller, verified, locationCreated from HTML source",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/open.js CHANGED
@@ -33,15 +33,13 @@ export async function handleOpen(parsed) {
33
33
  if (!openPort) {
34
34
  console.error("用法: tt-help open <端口>");
35
35
  console.error("示例: tt-help open 9222");
36
- console.error("");
37
- console.error("可用端口: 9222 - 9231 (共 10 个)");
38
- console.error('运行 "tt-help open --list" 查看所有配置');
36
+ console.error('运行 "tt-help open --list" 查看所有内置配置');
39
37
  process.exit(1);
40
38
  }
41
39
 
42
40
  const port = parseInt(openPort);
43
- if (isNaN(port) || port < BASE_PORT || port >= BASE_PORT + TOTAL_ACCOUNTS) {
44
- console.error(`端口 ${openPort} 不在有效范围内 (9222 - 9231)`);
41
+ if (isNaN(port) || port < 1 || port > 65535) {
42
+ console.error(`端口 ${openPort} 无效,请输入 1-65535 之间的端口号`);
45
43
  process.exit(1);
46
44
  }
47
45
 
@@ -9,7 +9,7 @@ const DEFAULT_WAF_TTL = 120000;
9
9
  const DEFAULT_WARM_URL = "https://www.tiktok.com/@nike";
10
10
  const BROWSER_CLOSE_TIMEOUT = 5000;
11
11
  const DEFAULT_MAX_REQUESTS_PER_PAGE = 50;
12
- const FALLBACK_PROFILE_PORT = 9222;
12
+ const FALLBACK_PROFILE_PORT = 9999;
13
13
 
14
14
  function delay(ms) {
15
15
  return new Promise((r) => setTimeout(r, ms));
@@ -120,10 +120,11 @@ export class TikTokScraper {
120
120
  this.slotIdx = 0;
121
121
  this.lastWarmTime = 0;
122
122
  this.warmPromise = null;
123
- this._fallbackBrowser = null;
124
- this._fallbackContext = null;
125
- this._fallbackSlots = [];
126
- this._fallbackSlotIdx = 0;
123
+ // 登录态 pool(init 时直接启动)
124
+ this.authBrowser = null;
125
+ this.authContext = null;
126
+ this.authSlots = [];
127
+ this.authSlotIdx = 0;
127
128
  }
128
129
 
129
130
  async init() {
@@ -141,23 +142,19 @@ export class TikTokScraper {
141
142
  this.browser = browser;
142
143
  this.context = context;
143
144
  this.slots = slots;
144
- await this.warmWaf();
145
- }
146
145
 
147
- async _ensureFallback(executablePath) {
148
- if (this._fallbackContext) return;
146
+ // 启动登录态 pool(1 个 slot)
149
147
  const fallbackDir = getFallbackProfileDir();
150
- console.error(
151
- `[TikTokScraper] 无登录态获取失败,fallback 到登录态 profile: ${fallbackDir}`,
152
- );
153
- const { browser, context, slots } = await initContext(
154
- executablePath,
155
- 1,
156
- fallbackDir,
157
- );
158
- this._fallbackBrowser = browser;
159
- this._fallbackContext = context;
160
- this._fallbackSlots = slots;
148
+ const {
149
+ browser: authBrowser,
150
+ context: authContext,
151
+ slots: authSlots,
152
+ } = await initContext(executablePath, 1, fallbackDir);
153
+ this.authBrowser = authBrowser;
154
+ this.authContext = authContext;
155
+ this.authSlots = authSlots;
156
+
157
+ await this.warmWaf();
161
158
  }
162
159
 
163
160
  async close() {
@@ -183,20 +180,20 @@ export class TikTokScraper {
183
180
  }
184
181
  };
185
182
 
186
- // 无登录态的 browser 是 chromium.launch() 返回的,直接 close
183
+ // 无登录态的 browser
187
184
  await closeAll(this.browser);
188
- // fallback context launchPersistentContext 返回的,直接 close
189
- if (this._fallbackContext) {
185
+ // 登录态的 context(launchPersistentContext 返回的是 context browser)
186
+ if (this.authContext) {
190
187
  try {
191
- await this._fallbackContext.close();
188
+ await this.authContext.close();
192
189
  } catch {}
193
190
  }
194
191
  this.browser = null;
195
192
  this.context = null;
196
193
  this.slots = [];
197
- this._fallbackBrowser = null;
198
- this._fallbackContext = null;
199
- this._fallbackSlots = [];
194
+ this.authBrowser = null;
195
+ this.authContext = null;
196
+ this.authSlots = [];
200
197
  }
201
198
 
202
199
  async restart() {
@@ -237,11 +234,6 @@ export class TikTokScraper {
237
234
  return Date.now() - this.lastWarmTime > this.wafTtl;
238
235
  }
239
236
 
240
- _pickSlot(slots, idx, setIdx) {
241
- const slot = slots[idx % slots.length];
242
- return slot;
243
- }
244
-
245
237
  async _ensurePage(slot, context) {
246
238
  try {
247
239
  if (
@@ -258,13 +250,11 @@ export class TikTokScraper {
258
250
  }
259
251
 
260
252
  async _fetchViewSource(url, ctx) {
261
- const slots =
262
- ctx === this._fallbackContext ? this._fallbackSlots : this.slots;
263
- const slotIdx =
264
- ctx === this._fallbackContext ? this._fallbackSlotIdx : this.slotIdx;
253
+ const slots = ctx === this.authContext ? this.authSlots : this.slots;
254
+ const slotIdx = ctx === this.authContext ? this.authSlotIdx : this.slotIdx;
265
255
  const slot = slots[slotIdx % slots.length];
266
- if (ctx === this._fallbackContext) {
267
- this._fallbackSlotIdx++;
256
+ if (ctx === this.authContext) {
257
+ this.authSlotIdx++;
268
258
  } else {
269
259
  this.slotIdx++;
270
260
  }
@@ -329,11 +319,9 @@ export class TikTokScraper {
329
319
  result = rawHtml ? parseUserInfo(rawHtml) : null;
330
320
  }
331
321
 
332
- // 仍然失败:fallback 到登录态
322
+ // 仍然失败:使用登录态 pool
333
323
  if (!result) {
334
- const executablePath = detectBrowser();
335
- await this._ensureFallback(executablePath);
336
- rawHtml = await this._fetchViewSource(url, this._fallbackContext);
324
+ rawHtml = await this._fetchViewSource(url, this.authContext);
337
325
  result = rawHtml ? parseUserInfo(rawHtml) : null;
338
326
  }
339
327
 
@@ -354,11 +342,9 @@ export class TikTokScraper {
354
342
  result = rawHtml ? parseVideoInfo(rawHtml) : null;
355
343
  }
356
344
 
357
- // 仍然失败:fallback 到登录态
345
+ // 仍然失败:使用登录态 pool
358
346
  if (!result) {
359
- const executablePath = detectBrowser();
360
- await this._ensureFallback(executablePath);
361
- rawHtml = await this._fetchViewSource(videoUrl, this._fallbackContext);
347
+ rawHtml = await this._fetchViewSource(videoUrl, this.authContext);
362
348
  result = rawHtml ? parseVideoInfo(rawHtml) : null;
363
349
  }
364
350