/ clis / jd / reviews.js
reviews.js
 1  import { cli, Strategy } from '@jackwener/opencli/registry';
 2  import { clampInt, normalizeNumericId } from '../_shared/common.js';
 3  cli({
 4      site: 'jd',
 5      name: 'reviews',
 6      description: '京东商品评价',
 7      domain: 'item.jd.com',
 8      strategy: Strategy.COOKIE,
 9      args: [
10          { name: 'sku', positional: true, required: true, help: '商品 SKU ID' },
11          { name: 'limit', type: 'int', default: 10, help: '返回评价数量 (max 20)' },
12      ],
13      columns: ['rank', 'user', 'content', 'date'],
14      navigateBefore: false,
15      func: async (page, kwargs) => {
16          const sku = normalizeNumericId(kwargs.sku, 'sku', '100291143898');
17          const limit = clampInt(kwargs.limit, 10, 1, 20);
18          await page.goto(`https://item.jd.com/${sku}.html`);
19          await page.wait(5);
20          await page.autoScroll({ times: 2, delayMs: 1500 });
21          const data = await page.evaluate(`
22        (async () => {
23          const text = document.body?.innerText || '';
24          const reviewStart = text.indexOf('买家评价');
25          const reviewEnd = text.indexOf('全部评价');
26          if (reviewStart < 0) return [];
27  
28          const reviewSection = text.substring(reviewStart, reviewEnd > reviewStart ? reviewEnd : reviewStart + 3000);
29          const lines = reviewSection.split('\\n').map(l => l.trim()).filter(Boolean);
30  
31          const results = [];
32          const userPattern = /^[a-zA-Z0-9*_]{3,15}$/;
33          for (let i = 0; i < lines.length; i++) {
34            const line = lines[i];
35            if (userPattern.test(line) && line.includes('*') && i + 1 < lines.length) {
36              const user = line;
37              const content = lines[i + 1];
38              if (content.length < 5 || content.match(/^(全部评价|问大家|查看更多)/)) continue;
39              results.push({
40                rank: results.length + 1,
41                user,
42                content: content.slice(0, 150),
43                date: '',
44              });
45              i++;
46              if (results.length >= ${limit}) break;
47            }
48          }
49          return results;
50        })()
51      `);
52          return Array.isArray(data) ? data : [];
53      },
54  });