| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- #!/usr/bin/env node
- /**
- * 探测 TikHub TikTok 端点的可用性
- * 关键:TikTok 不需要 cookie 登录态(海外版)
- * 产品目标:
- * - liver → milk thistle
- * - probiotic → kids probiotics
- * - monkey → lions mane
- */
- const fs = require('fs');
- const path = require('path');
- const os = require('os');
- const https = require('https');
- const TOKEN = JSON.parse(
- fs.readFileSync(
- path.join(os.homedir(), '.openclaw', 'skills', 'xiaohongshu-search-notes', 'api-config.json'),
- 'utf-8'
- )
- ).endpoint.headers.Authorization.replace(/^Bearer\s+/, '');
- function get(apiPath) {
- return new Promise((resolve) => {
- const opts = {
- hostname: 'api.tikhub.io',
- path: apiPath,
- method: 'GET',
- headers: { Authorization: `Bearer ${TOKEN}`, Accept: 'application/json' },
- };
- const req = https.request(opts, (res) => {
- const chunks = [];
- res.on('data', (c) => chunks.push(c));
- res.on('end', () => {
- const body = Buffer.concat(chunks).toString('utf-8');
- try { resolve({ status: res.statusCode, json: JSON.parse(body) }); }
- catch (e) { resolve({ status: res.statusCode, text: body.slice(0, 300) }); }
- });
- });
- req.on('error', (e) => resolve({ status: 0, error: e.message }));
- req.setTimeout(45000, () => { req.destroy(); resolve({ status: 0, error: 'timeout' }); });
- req.end();
- });
- }
- const kw = 'milk thistle';
- const kwE = encodeURIComponent(kw);
- // 测试候选路径:视频搜 + 用户搜 + 关键词相关
- const paths = [
- // app v3 系列
- `/api/v1/tiktok/app/v3/fetch_video_search_result?keyword=${kwE}&cursor=0&count=10`,
- `/api/v1/tiktok/app/v3/fetch_general_search_result?keyword=${kwE}&cursor=0&count=10`,
- `/api/v1/tiktok/app/v3/fetch_user_search_result?keyword=${kwE}&cursor=0&count=10`,
- // web 系列
- `/api/v1/tiktok/web/fetch_video_search_result?keyword=${kwE}&cursor=0&count=10`,
- `/api/v1/tiktok/web/fetch_general_search_result?keyword=${kwE}&cursor=0&count=10`,
- `/api/v1/tiktok/web/fetch_user_search_result?keyword=${kwE}&cursor=0&count=10`,
- `/api/v1/tiktok/web/fetch_search_video?keyword=${kwE}&cursor=0&count=10`,
- `/api/v1/tiktok/web/fetch_search_user?keyword=${kwE}&cursor=0&count=10`,
- // V2
- `/api/v1/tiktok/app/v3/fetch_video_search_result_v2?keyword=${kwE}&cursor=0&count=10`,
- // 不带 app/web 前缀
- `/api/v1/tiktok/fetch_video_search_result?keyword=${kwE}&cursor=0&count=10`,
- ];
- (async () => {
- const results = [];
- for (const p of paths) {
- const r = await get(p);
- const code = r.json?.code;
- const msg = (r.json?.message_zh || r.json?.message || '').slice(0, 60);
- const d = r.json?.data;
- let hint = '';
- if (d) {
- const inner = d.data || d.aweme_list || d.user_list || null;
- if (Array.isArray(d)) hint = `arr[${d.length}]`;
- else if (inner && Array.isArray(inner)) hint = `arr[${inner.length}]` + (inner[0] ? ` first_keys=${Object.keys(inner[0]).slice(0, 5).join(',')}` : '');
- else hint = 'keys=' + Object.keys(d).slice(0, 6).join(',');
- }
- console.log(`[${r.status}] ${p.split('?')[0].replace('/api/v1/tiktok/', '')}`);
- console.log(` code=${code} msg="${msg}" hint=${hint}`);
- results.push({ path: p, status: r.status, code, msg, hint });
- await new Promise((res) => setTimeout(res, 700));
- }
- fs.writeFileSync('data/tiktok-probe.json', JSON.stringify(results, null, 2), 'utf-8');
- console.log('\n✓ data/tiktok-probe.json');
- })();
|