Add archived/atomk-bulk-claim
This commit is contained in:
@@ -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/
|
||||
```
|
||||
Reference in New Issue
Block a user