| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #!/usr/bin/env node
- /**
- * 抖音账号搜索探测:用 TikHub /fetch_user_search_result 搜用户
- * 对 6 个候选关键词搜索,返回 Top 3 用户(昵称 / sec_uid / 粉丝)
- */
- const fs = require('fs');
- const path = require('path');
- const os = require('os');
- const https = require('https');
- const TIKHUB_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+/, '');
- const COOKIE = fs.readFileSync(path.resolve('data/douyin-cookie.txt'), 'utf-8').trim();
- function get(apiPath, params) {
- params.cookie = COOKIE;
- const qs = Object.entries(params)
- .filter(([, v]) => v !== undefined && v !== null && v !== '')
- .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
- .join('&');
- return new Promise((resolve) => {
- const opts = {
- hostname: 'api.tikhub.io',
- path: `${apiPath}?${qs}`,
- method: 'GET',
- headers: { Authorization: `Bearer ${TIKHUB_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, json: { _raw: body.slice(0, 300) } });
- }
- });
- });
- req.on('error', (e) => resolve({ status: 0, json: { _error: e.message } }));
- req.setTimeout(30000, () => { req.destroy(); resolve({ status: 0, json: { _error: 'timeout' } }); });
- req.end();
- });
- }
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- // 关键词 × 产品 候选列表
- const candidates = [
- // liver 肝纯片
- { product: 'liver', role: '品牌竞品号', keyword: '葵花护肝片' },
- { product: 'liver', role: '品牌竞品号', keyword: '葵花药业' },
- { product: 'liver', role: '垂类博主', keyword: '肝病科' },
- { product: 'liver', role: '垂类博主', keyword: '护肝科普' },
- // probiotic 儿童乳酸菌
- { product: 'probiotic', role: '品牌竞品号', keyword: '妈咪爱' },
- { product: 'probiotic', role: '品牌竞品号', keyword: '亿活益生菌' },
- { product: 'probiotic', role: '品牌竞品号', keyword: '合生元' },
- { product: 'probiotic', role: '垂类博主', keyword: '儿科医生' },
- { product: 'probiotic', role: '垂类博主', keyword: '崔玉涛' },
- // monkey 猴菇饮
- { product: 'monkey', role: '品牌竞品号', keyword: '康恩贝' },
- { product: 'monkey', role: '品牌竞品号', keyword: '太阳神' },
- { product: 'monkey', role: '品牌竞品号', keyword: '三九胃泰' },
- { product: 'monkey', role: '垂类博主', keyword: '胃肠科医生' },
- { product: 'monkey', role: '垂类博主', keyword: '养胃' },
- ];
- (async () => {
- const out = [];
- for (const c of candidates) {
- await sleep(1200);
- console.log(`\n[${c.product} · ${c.role}] 搜 "${c.keyword}"`);
- // TikHub 的用户搜索接口(v2 可用)
- const r = await get('/api/v1/douyin/web/fetch_user_search_result_v2', {
- keyword: c.keyword,
- search_channel: 'aweme_user_web',
- sort_type: 0,
- publish_time: 0,
- page: 1,
- count: 10,
- });
- const data = r.json?.data;
- const users = Array.isArray(data) ? data : (data?.user_list || data?.users || data?.data || []);
- if (!Array.isArray(users) || users.length === 0) {
- console.log(' ❌ no users. raw:', JSON.stringify(r.json).slice(0, 250));
- out.push({ ...c, users: [], error: r.json?.message_zh || r.json?.message || 'empty' });
- continue;
- }
- const top = users.slice(0, 3).map((u) => {
- const uinfo = u.user_info || u;
- return {
- nickname: uinfo.nickname,
- sec_uid: uinfo.sec_uid,
- uid: uinfo.uid,
- follower_count: uinfo.follower_count,
- custom_verify: uinfo.custom_verify,
- signature: (uinfo.signature || '').replace(/\n/g, ' ').slice(0, 60),
- share_url: uinfo.sec_uid ? `https://www.douyin.com/user/${uinfo.sec_uid}` : '',
- };
- });
- console.log(' top candidates:');
- top.forEach((t, i) => {
- console.log(` #${i + 1} ${t.nickname} · 粉丝 ${(t.follower_count || 0).toLocaleString()} · ${t.custom_verify || '-'}`);
- console.log(` sec_uid: ${t.sec_uid}`);
- });
- out.push({ ...c, users: top });
- }
- const outPath = path.resolve('data', 'dy-user-candidates.json');
- fs.writeFileSync(outPath, JSON.stringify(out, null, 2), 'utf-8');
- console.log('\n\n✓ Wrote', outPath);
- console.log('共搜 ' + out.length + ' 个关键词');
- })();
|