probe-dy-search-get-v2.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/env node
  2. /**
  3. * 405 说明端点存在但不接 POST → 回退 GET + cookie 测试 result_v2 系列
  4. */
  5. const fs = require('fs');
  6. const path = require('path');
  7. const os = require('os');
  8. const https = require('https');
  9. const TIKHUB_TOKEN = JSON.parse(
  10. fs.readFileSync(
  11. path.join(os.homedir(), '.openclaw', 'skills', 'xiaohongshu-search-notes', 'api-config.json'),
  12. 'utf-8'
  13. )
  14. ).endpoint.headers.Authorization.replace(/^Bearer\s+/, '');
  15. const COOKIE = fs.readFileSync(path.resolve('data/douyin-cookie.txt'), 'utf-8').trim();
  16. function get(apiPath, params) {
  17. const qs = Object.entries(params)
  18. .filter(([, v]) => v !== undefined && v !== null && v !== '')
  19. .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
  20. .join('&');
  21. return new Promise((resolve) => {
  22. const opts = {
  23. hostname: 'api.tikhub.io',
  24. path: `${apiPath}?${qs}`,
  25. method: 'GET',
  26. headers: { Authorization: `Bearer ${TIKHUB_TOKEN}`, Accept: 'application/json' },
  27. };
  28. const req = https.request(opts, (res) => {
  29. const chunks = [];
  30. res.on('data', (c) => chunks.push(c));
  31. res.on('end', () => {
  32. const body = Buffer.concat(chunks).toString('utf-8');
  33. try {
  34. resolve({ status: res.statusCode, json: JSON.parse(body) });
  35. } catch (e) {
  36. resolve({ status: res.statusCode, text: body.slice(0, 200) });
  37. }
  38. });
  39. });
  40. req.on('error', (e) => resolve({ status: 0, error: e.message }));
  41. req.setTimeout(30000, () => { req.destroy(); resolve({ status: 0, error: 'timeout' }); });
  42. req.end();
  43. });
  44. }
  45. const paths = [
  46. '/api/v1/douyin/app/v3/fetch_video_search_result_v2',
  47. '/api/v1/douyin/app/v3/fetch_user_search_result_v2',
  48. '/api/v1/douyin/web/fetch_video_search_result_v2',
  49. '/api/v1/douyin/web/fetch_user_search_result_v2',
  50. ];
  51. (async () => {
  52. const results = [];
  53. for (const p of paths) {
  54. const r = await get(p, {
  55. keyword: '康恩贝',
  56. cursor: 0,
  57. sort_type: 0,
  58. publish_time: 0,
  59. count: 10,
  60. cookie: COOKIE,
  61. });
  62. const topCode = r.json?.code;
  63. const topMsg = (r.json?.message_zh || r.json?.message || '').slice(0, 60);
  64. const d = r.json?.data;
  65. let innerStr = '';
  66. if (d) {
  67. if (typeof d === 'string') innerStr = d.slice(0, 80);
  68. else if (Array.isArray(d)) innerStr = `arr[${d.length}]`;
  69. else {
  70. const inner = d.data;
  71. if (typeof inner === 'string') innerStr = 'str: ' + inner.slice(0, 80);
  72. else if (Array.isArray(inner)) innerStr = `arr[${inner.length}] first keys=${inner[0] ? Object.keys(inner[0]).slice(0, 5).join(',') : ''}`;
  73. else innerStr = 'obj keys=' + Object.keys(d).slice(0, 6).join(',') + (inner ? '; inner obj keys=' + Object.keys(inner).slice(0, 6).join(',') : '');
  74. }
  75. }
  76. console.log(`[${r.status}] ${p}`);
  77. console.log(` top code=${topCode} msg="${topMsg}"`);
  78. console.log(` inner: ${innerStr}`);
  79. results.push({ path: p, status: r.status, code: topCode, msg: topMsg, inner: innerStr });
  80. await new Promise((res) => setTimeout(res, 800));
  81. }
  82. fs.writeFileSync('data/dy-search-get-v2.json', JSON.stringify(results, null, 2), 'utf-8');
  83. // 额外:把 video_search_result_v2 的完整响应 dump 出来
  84. const detail = await get('/api/v1/douyin/app/v3/fetch_video_search_result_v2', {
  85. keyword: '康恩贝',
  86. cursor: 0,
  87. sort_type: 0,
  88. publish_time: 0,
  89. count: 10,
  90. cookie: COOKIE,
  91. });
  92. fs.writeFileSync('data/dy-search-get-v2-sample.json', JSON.stringify(detail.json, null, 2).slice(0, 20000), 'utf-8');
  93. })();