cart.js
1 import { AuthRequiredError } from '@jackwener/opencli/errors'; 2 import { cli, Strategy } from '@jackwener/opencli/registry'; 3 import { clampInt } from '../_shared/common.js'; 4 cli({ 5 site: 'taobao', 6 name: 'cart', 7 description: '查看淘宝购物车', 8 domain: 'cart.taobao.com', 9 strategy: Strategy.COOKIE, 10 args: [ 11 { name: 'limit', type: 'int', default: 20, help: '返回数量 (max 50)' }, 12 ], 13 columns: ['index', 'title', 'price', 'spec', 'shop'], 14 navigateBefore: false, 15 func: async (page, kwargs) => { 16 const limit = clampInt(kwargs.limit, 20, 1, 50); 17 await page.goto('https://www.taobao.com'); 18 await page.wait(2); 19 await page.evaluate(`location.href = 'https://cart.taobao.com/cart.htm'`); 20 await page.wait(6); 21 await page.autoScroll({ times: 3, delayMs: 1500 }); 22 const data = await page.evaluate(` 23 (async () => { 24 const text = document.body?.innerText || ''; 25 if (text.length < 500 || text.includes('请登录')) { 26 return { error: 'auth-required' }; 27 } 28 29 const sections = text.split(/移入收藏/); 30 const results = []; 31 32 for (const section of sections) { 33 const lines = section.split('\\n').map(l => l.trim()).filter(Boolean); 34 if (lines.length < 3) continue; 35 36 let title = ''; 37 let titleIdx = -1; 38 for (let i = 0; i < lines.length; i++) { 39 const l = lines[i]; 40 if (l.length > 15 && l.length < 200 && !l.match(/^(删除|全选|全部商品|合计|结算|找同款|退货|¥|¥|\\d+$|颜色|尺码|规格|套餐|主板|运行)/)) { 41 if (l.length > title.length) { 42 title = l; 43 titleIdx = i; 44 } 45 } 46 } 47 if (!title) continue; 48 49 let price = ''; 50 for (let i = 0; i < lines.length; i++) { 51 if (lines[i] === '¥' || lines[i] === '¥') { 52 let p = ''; 53 for (let j = i + 1; j < Math.min(i + 4, lines.length); j++) { 54 if (lines[j].match(/^[\\d,.]+$/)) p += lines[j]; 55 else if (lines[j] === '.') p += '.'; 56 else break; 57 } 58 if (p) { price = '¥' + p; break; } 59 } 60 } 61 62 let spec = ''; 63 for (const l of lines) { 64 if (l.match(/^(颜色分类|尺码|规格|套餐|主板|运行)[::]/)) { 65 spec = l.slice(0, 40); 66 break; 67 } 68 } 69 70 let shop = ''; 71 if (titleIdx > 0) { 72 const prev = lines[titleIdx - 1]; 73 if (prev && prev.length > 2 && prev.length < 30 && !prev.match(/^(删除|\\d|¥|¥|券|退|满|超)/)) { 74 shop = prev; 75 } 76 } 77 78 results.push({ 79 index: results.length + 1, 80 title: title.slice(0, 80), 81 price, 82 spec, 83 shop, 84 }); 85 if (results.length >= ${limit}) break; 86 } 87 return { results }; 88 })() 89 `); 90 if (data?.error === 'auth-required') { 91 throw new AuthRequiredError('taobao cart requires a logged-in Taobao session'); 92 } 93 return Array.isArray(data?.results) ? data.results : []; 94 }, 95 });