From 5c3dd187a992f3c0504f6dfa32c8b8c45d68bc82 Mon Sep 17 00:00:00 2001 From: admin9webs Date: Fri, 10 Jul 2026 16:10:33 +0800 Subject: [PATCH] Add archived/atomk-bulk-claim --- skills/archived/atomk-bulk-claim/SKILL.md | 126 ++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 skills/archived/atomk-bulk-claim/SKILL.md diff --git a/skills/archived/atomk-bulk-claim/SKILL.md b/skills/archived/atomk-bulk-claim/SKILL.md new file mode 100644 index 0000000..757d69b --- /dev/null +++ b/skills/archived/atomk-bulk-claim/SKILL.md @@ -0,0 +1,126 @@ +--- +name: atomk-bulk-claim +description: Automatically log into AtomK, claim products from Product Pool, generate Temu/AliExpress data, and download CSV with 800x800 images using Node.js Playwright. +--- + +# AtomK Product Claim & Temu Data Generation + +Automates logging into the AtomK system (atomlisting.com), claiming products from the Product Pool (产品池), generating Temu listing data via AI, and exporting CSV with 800x800 images. + +## Critical Environment Facts +- **DrissionPage is NOT installed** — do NOT use it +- **Use Node.js Playwright** at `/home/ubuntu/.hermes/hermes-agent/node_modules/playwright` +- **Use `atomlisting.com` domain** — `bt109atomk.sh3.ikuai7.com` login silently fails +- Login credentials: admincao / Tt123456! +- `sharp` npm package required for image resizing (`npm install sharp`) +- Set `NODE_PATH=/home/ubuntu/.hermes/hermes-agent/node_modules` when running scripts +- Use `ignoreHTTPSErrors: true` for atomlisting.com + +## Execution Steps + +### 1. Setup +```bash +killall -9 chrome chromium chrome-headless-shell 2>/dev/null +cd /home/ubuntu/.hermes/hermes-agent && NODE_PATH=/home/ubuntu/.hermes/hermes-agent/node_modules node script.js +``` + +### 2. Login +Navigate to `https://atomlisting.com/login` (NO www, HTTPS only). Fill inputs[0] with username, inputs[1] with password, then `await inputs[1].press('Enter')` — do NOT click the login button. The form has `method="get"` and clicking the button triggers a GET redirect to `login?` instead of the JavaScript-powered `POST /api/v1/auth/login`. Pressing Enter on the password field triggers the correct JS handler. + +### 3. Claim Products +1. Navigate to `https://atomlisting.com/products` (use `waitUntil: 'domcontentloaded'`) +2. Select category: `await page.selectOption('select', { label: '家居百货' })` +3. Click refresh button: `text=刷新` +4. Find claim buttons: `page.$$('text=认领并编辑')` +5. For each button: + - Extract product ID using regex `/^[A-Z0-9]{6,8}$/` from card text + - Click button, wait for URL to contain `/editor/` + - Extract editor ID from URL + - Navigate back to products, re-select category + +### 2a. Searching for Existing Products (Product Lookup) +AtomK has **two separate product views**: + +| Page | URL | Contains | +|------|-----|----------| +| **Product Pool** (`产品池`) | `https://atomlisting.com/products` | Unclaimed products available for claiming | +| **My Products** (`我的产品`) | `https://atomlisting.com/my-products` | Products already claimed by current account | + +**Search strategy:** +- Use **product name prefix** (e.g. `88NeoHab`, `11Chughalf`) rather than the full SKU (`88NeoHab-PO-211-16060374487670113`). The full SKU often returns no results because AtomK indexes by product code, not the full platform SKU. +- If a product is **not found** in My Products, check the Product Pool — it may not have been claimed yet. +- The search input may not be visible immediately on page load; wait for the SPA to render. + +```javascript +// Search in Product Pool +await page.goto('https://atomlisting.com/products'); +await page.waitForTimeout(3000); +const searchInput = page.locator('input[placeholder*="搜索"]').first(); +await searchInput.fill('88NeoHab'); // prefix, not full SKU +await searchInput.press('Enter'); +await page.waitForTimeout(5000); +``` + +### 4. Generate Platform Data (Temu / AliExpress / etc.) +For each claimed product: +1. Navigate to `https://atomlisting.com/editor/{id}` +2. Click platform tab button first — available platforms: `button:has-text("Temu")`, `button:has-text("速卖通")`, `button:has-text("亚马逊")`, `button:has-text("TikTok Shop")`, `button:has-text("SHEIN")`, `button:has-text("Ozon")`, `button:has-text("沃尔玛")` +3. Click `button:has-text("AI 生成")` — the button text becomes `AI 生成 速卖通 上架信息` after platform selection +4. Wait for generation (poll button text until no longer contains "生成中") +5. Extract generated data: + - Title: `input[placeholder*="标题"]` or `input[placeholder*="产品标题"]` + - Description: `textarea[placeholder*="描述"]` or `textarea[placeholder*="产品描述"]` + - Price: `input[type="number"]` + - Tags: `input[placeholder*="关键词"]` or `input[placeholder*="标签"]` + - Image URLs: `img[src*="cos"]` (both cos.ap-hongkong and cos.ap-nanjing sources, exclude logo/icon) + - Dimensions: inputs with placeholders for 重量/长/宽/高 + +**AliExpress CSV format** (similar to Temu but different category defaults): +``` +Product name,Category path,Price,Quantity,Product description,Package weight,Package length,Package width,Package height,Keywords,Image URLs,Product code +``` +Use "Luggage & Bags" as category for 箱包 products. + +### 5. Download & Resize Images +```javascript +const sharp = require('sharp'); +const { execSync } = require('child_process'); + +// Download +execSync(`curl -sL -o "${tempFile}" "${url}"`, { timeout: 30000 }); + +// Resize to 800x800 +const resized = await sharp(tempFile) + .resize(800, 800, { fit: 'contain', background: { r: 255, g: 255, b: 255, alpha: 1 } }) + .jpeg({ quality: 90 }) + .toBuffer(); +``` + +### 6. Generate CSV +Temu standard format: +``` +Product name,Category path,Price,Quantity,Product description,Package weight,Package length,Package width,Package height,Keywords,Image URLs,SKU,Product code +``` + +CSV fields must be escaped: if value contains `,`, `"`, or `\n`, wrap in `"` and double any `"`. + +## Critical Pitfalls +- **Login form GET trap**: The login form has `method="get"` — clicking the "登 录" button submits a GET request to `login?` and stays on the login page. Always press Enter on the password field to trigger the JS `POST /api/v1/auth/login` handler instead. +- **Available categories in Product Pool**: "全部分类", "汽摩配", "玩具母婴", "箱包" (bags-luggage), "服饰配饰", "美妆个护", "服饰", "美容健康", "默认分类", "文具电子", "家居百货", "运动户外". Use `page.selectOption('select', { label: '箱包' })` for bags/luggage. +- **Platform tabs in Editor**: After claiming, the editor supports multiple platforms. Click the platform tab FIRST (e.g., `速卖通`, `Temu`, `亚马逊`, `TikTok Shop`, `SHEIN`, `Ozon`, `沃尔玛`), THEN click AI generate. The AI generate button text changes to reflect the selected platform (e.g., "AI 生成 速卖通 上架信息"). +- **Image sources include both regions**: Generated product images may come from both `cos.ap-hongkong.myqcloud.com` (user uploads) AND `cos.ap-nanjing.myqcloud.com` (1688 source images). Filter with `img[src*="cos"]` instead of just hongkong. +- **Product ID parsing**: Don't use line position (lines[0]). Use regex `/^[A-Z0-9]{6,8}$/` to find the 6-8 char alphanumeric product code. First line can be "暂无图片" or image count. +- **Editor ID validation**: Must be numeric (`/^\d+$/`). Some claimed products lead to non-editor pages. +- **Stale element references**: After clicking a claim button, the page navigates. Re-find elements after each navigation back to products. +- **AI generation timeout**: Each product takes 1-3 minutes. Use generous polling (50 iterations × 3 seconds = 150 seconds max). +- **Background processes**: For 20+ products, use `terminal(background=true, notify_on_complete=true)` with timeout > 600s. +- **Playwright waitUntil**: Use `domcontentloaded` not `networkidle` for heavy pages — faster and more reliable. +- **Suppress alerts**: Use `page.addInitScript(() => { window.alert = function() {}; window.confirm = function() { return true; }; })` to prevent blocking dialogs. +- **sharp module path**: Must set `NODE_PATH` environment variable or require will fail with "Cannot find module 'sharp'". +- **HTTPS certificate errors**: atomlisting.com has a cert mismatch. Set `ignoreHTTPSErrors: true` at BOTH `chromium.launch()` AND `browser.newContext()` levels. +- **Download blocking**: Cannot use `page.goto()` for image URLs that trigger downloads. Use `curl` via `execSync` instead. + +## Archive Output +```bash +cd /tmp && tar -czf temu_batch_20.tar.gz temu_batch_listing_final.csv temu_batch_images_800x800/ +``` \ No newline at end of file