Files
atomk-hermes-skills/skills/archived/atomk-bulk-claim/SKILL.md
T

126 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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/
```