mcpField
L
linkfox-walmart-wmtwin

linkfox-walmart-wmtwin

github.com/linkfox-aiMarketing & growth11361 installsUpdated 2w ago
Repository

About linkfox-walmart-wmtwin

linkfox-walmart-wmtwin is a skill for Walmart sellers using WMTwin, covering login, API calls, and competitor searches. It reuses saved sessions, paginates larger searches, and decodes returned data; CAPTCHA and SMS codes still require user input.

Key features

  1. 01Automated login and session persistence
  2. 02Separate sessions for multiple phone numbers
  3. 03Keyword and filter-based competitor search
  4. 04Automatic pagination beyond the page limit
  5. 05Automatic decoding of API responses

Use cases

  1. 01Log in to WMTwin and query account APIs
  2. 02Filter competitors by sales or price
  3. 03Find WFS products or a named seller
  4. 04Prepare decoded search results

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/linkfox-ai/linkfox-skills --skill linkfox-walmart-wmtwin

After installing, type/linkfox-walmart-wmtwinin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
api.md
competitor_search.md
scripts/
response_io.py
wmtwin_complete_decoder.py
wmtwin_login.py
wmtwin_search_competitors.py

Details

From the project README

沃师傅(WMTwin) 自动化登录与竞品搜索

This skill provides automated login, API calling and competitor search capabilities for WMTwin (沃师傅), a Walmart seller tool platform. It handles authentication flow and competitor product search with automatic data decoding.

Core Concepts

沃师傅(WMTwin) 是沃尔玛卖家工具平台。本技能提供自动化登录、API调用和竞品搜索功能,包括:

登录与认证
  • 自动登录管理: 检测登录状态,自动执行登录流程
  • 图形验证码: 需要人工识别,系统会展示图片给用户
  • 短信验证码: 自动发送,用户提供验证码完成登录
  • Session持久化: 登录成功后保存session,避免重复登录
  • 多账号支持: 每个手机号独立管理session
竞品搜索
  • 关键词搜索: 按关键词搜索沃尔玛平台竞品
  • WFS筛选: 只搜索 Walmart Fulfillment Services 商品
  • 销量范围: 按最小/最大销量筛选产品
  • 分页查询: 支持大量数据的分页获取
  • 自动解码: 所有编码字符自动转换为真实数据
  • 自动登录: 检测登录状态,未登录时自动引导用户登录
  • Session管理: 自动保存和加载登录状态,支持多账号

Authentication Flow

1. 尝试密码登录
   ├─ 成功 → 保存session,完成
   └─ 失败 (code: 1101) → 需要验证码登录

2. 获取图形验证码
   └─ 展示图片给用户,等待人工识别

3. 发送短信验证码
   └─ 使用图形验证码答案调用发送API

4. 短信验证码登录
   └─ 用户提供短信验证码,完成登录

5. 保存Session
   └─ Session保存在 /tmp/linkfox_wmtwin_sessions/{phone}.json

Important API Rules

Response Format

沃师傅的API响应格式特殊,需要注意:

成功响应:

{
  "code": 1,           // 注意:1表示成功,不是0!
  "msg": "成功",
  "data": {...}
}

失败响应:

{
  "code": 1101,        // 其他code表示失败
  "msg": "错误信息",
  "data": null
}

判断成功的条件:

def is_success(result):
    return result.get('code') in [0, 1] and result.get('msg') in ['成功', '操作成功']
Common Error Codes
Code含义处理方式
1成功正常处理
1101环境异常,需要验证码登录执行短信登录流程
1008验证码错误重新获取验证码
1020短信验证码错误检查验证码或重新发送

API Endpoints

Authentication APIs
EndpointMethodDescription
/api/v1/auth/loginPOST密码登录
/api/v1/auth/captchaGET获取图形验证码
/api/v1/auth/sms-codePOST发送短信验证码
/api/v1/auth/sms-loginPOST短信验证码登录

See references/api.md for detailed API documentation.

Usage

Step-by-Step Login
# 步骤1: 开始登录,获取验证码
python3 scripts/wmtwin_login.py login 13699998888 111111

# 系统会保存验证码图片: /tmp/linkfox_wmtwin_captcha.png
# 用户查看图片并提供答案(例如:24)

# 步骤2: 提供验证码,发送短信
python3 scripts/wmtwin_login.py continue 24

# 系统发送短信到用户手机
# 用户提供短信验证码(例如:123456)

# 步骤3: 完成登录
python3 scripts/wmtwin_login.py continue sms 123456

# 登录成功,session保存在:
# /tmp/linkfox_wmtwin_sessions/13699998888.json
Check Login Status
python3 scripts/wmtwin_login.py check 13699998888
Call API
# GET请求
python3 scripts/wmtwin_login.py api 13699998888 /user/info

# POST请求
python3 scripts/wmtwin_login.py api 13699998888 /order/create POST '{"item":"test"}'

Working with Session

Session Storage
  • Location: /tmp/linkfox_wmtwin_sessions/{phone}.json
  • Format: JSON containing cookies, headers, and timestamp
  • Auto-load: Automatically loaded when calling APIs
Session Structure
{
  "cookies": {
    "wal": "encoded_session_token"
  },
  "headers": {
    "User-Agent": "...",
    "Content-Type": "application/json"
  },
  "saved_at": "2024-04-28T16:28:08.987745"
}
Cookie Handling

Important: 沃师傅返回重复的cookie名称,需要特殊处理:

# 正确方式:避免重复cookie错误
cookies_dict = {}
for cookie in session.cookies:
    cookies_dict[cookie.name] = cookie.value  # 自动覆盖重复项

Password Encryption

密码使用RSA加密传输:

  • Algorithm: RSA 1024-bit + PKCS1 v1.5 padding
  • Encoding: Base64
  • Transport: HTTPS
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64

PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEICVdtxqOCBwHN9a/+YxeXz/B
ZGfduADPfV9dUTW+hGVpIcXU6kBkUdlhVPPdO6n7irK7dxD56m1xG1EmV2RICsvy
W2Y7JVyRRVhun92urbw7TtBcMCCB5SzLI+x1LBUr98SMkMNRQxcnYPkrPj0qGI4v
MC52dJ7z3n6aMf3XoQIDAQAB
-----END PUBLIC KEY-----"""

def encrypt_password(password):
    public_key = RSA.import_key(PUBLIC_KEY)
    cipher = PKCS1_v1_5.new(public_key)
    encrypted_bytes = cipher.encrypt(password.encode('utf-8'))
    return base64.b64encode(encrypted_bytes).decode('utf-8')

Data Decoding

沃师傅 API 返回的字符串常使用 Unicode U+0100–U+024F 区段的编码字符(在部分环境下看起来像乱码)。本技能通过 scripts/wmtwin_complete_decoder.py 自动解码;文档中的示例统一用 U+XXXX 码点 描述,不直接展示原始编码字形。

Encoding Ranges

沃师傅使用了4个编码范围,支持两套不同的编码方案:

编码范围Unicode映射用途方案
323单字符小数点 .价格小数点通用
324-33310字符数字 0-9简单数字(评论数等)API方案
334-38552字符A-Z, a-z卖家名称、公司名API方案
528单字符小数点 .价格小数点文档方案
529-53810字符数字 0-9数字文档方案
539-56426字符大写 A-Z大写字母文档方案
565-59026字符小写 a-z小写字母文档方案
Decoding Examples
# 编码示例
'U+0146' (326) → '2'                    # 评论数 (324-333)
'U+0152U+015FU+0156U+0150-U+0152U+0165U+015DU+015FU+0152U+0160U+0160' → 'ERIC-EXPRESS'      # 卖家名 (334-385)
'$U+0146U+0145U+0145U+0144U+0143U+0148U+0172+' → '$2110.4k+'           # 销售额 (323+324-333)
'U+0213' (531) → '2'                    # 数字 (529-538)
'U+021FU+022CU+0223U+021D-U+021FU+0232U+022AU+022CU+021FU+022DU+022D' → 'ERIC-EXPRESS'    # 卖家名 (539-564)
'$U+0213U+0212U+0212U+0211U+0210U+0215U+023F+' → '$2110.4k+'          # 销售额 (528-590)
Using the Decoder

完整解码器: scripts/wmtwin_complete_decoder.py

# 解码JSON文件
python3 scripts/wmtwin_complete_decoder.py input.json -o output.json

# 从标准输入解码
cat input.json | python3 scripts/wmtwin_complete_decoder.py - -o output.json

在代码中使用:

from scripts.wmtwin_complete_decoder import decode_json, decode_json_file

# 方法1: 解码JSON对象
import json
with open('input.json') as f:
    data = json.load(f)
decoded_data = decode_json(data)

# 方法2: 直接解码文件
decoded_data = decode_json_file('input.json', 'output.json')
Decoded Fields

解码器会递归解码JSON中的所有字符串字段,包括:

基本字段:

  • number_of_reviews: 评论数
  • additional_offer_count: 供应商数
  • sales_volume: 销量
  • sales_amount: 销售额

卖家字段 (sellers):

  • display_name: 卖家显示名称
  • name: 公司名称
  • seller_reviews: 卖家评论数
  • seller_rating: 卖家评分

销售趋势 (sales_trends):

  • sales_amount.label: 销售额标签(如 $2110.4k+)
  • sales_volume.label: 销量标签(如 197.0k+)
  • month_sales_growth: 月增长
  • gross_profit: 毛利
  • gross_profit_margin: 毛利率
Data Sources

不同数据源可能使用不同的编码方案:

  • API实时数据: 使用 323-385 范围(方案A)
  • 参考文件: 使用 528-590 范围(方案B)
  • 解码器支持: 同时支持两套方案
Verification

验证解码是否完整:

# 检查是否还有编码字符
encoded_ranges = [(323, 323), (324, 333), (334, 385), (528, 590)]

def has_encoded_chars(text):
    if not isinstance(text, str):
        return False
    for char in text:
        code = ord(char)
        for start, end in encoded_ranges:
            if start <= code <= end:
                return True
    return False

# 检查解码后的数据
import json
with open('decoded.json') as f:
    data = json.load(f)

# 递归检查所有字符串字段
def check_decoded(obj):
    if isinstance(obj, dict):
        return all(check_decoded(v) for v in obj.values())
    elif isinstance(obj, list):
        return all(check_decoded(item) for item in obj)
    elif isinstance(obj, str):
        return not has_encoded_chars(obj)
    return True

is_fully_decoded = check_decoded(data)
print(f"完全解码: {is_fully_decoded}")

In Conversation Usage

When the user mentions 沃师傅 or related keywords, this skill is automatically triggered. Follow these steps:

  1. Check login status:

    from scripts.wmtwin_login import load_session
    session = load_session(phone)
    
  2. If not logged in, guide the user:

    • Start login process
    • Display CAPTCHA image to user
    • Ask user for CAPTCHA answer
    • Send SMS code
    • Ask user for SMS code
    • Complete login
  3. Call API with session:

    from scripts.wmtwin_login import call_api
    result = call_api(phone, endpoint, method, data)
    

Best Practices

  1. Always check login before API calls - Avoid 401/403 errors
  2. Show CAPTCHA image to user - Human input required for graphical CAPTCHA
  3. Clear error messages - Guide user through each step
  4. Session reuse - Don't login repeatedly if session exists
  5. Multi-account support - Each phone number has independent session

Debugging

View CAPTCHA
# macOS
open /tmp/linkfox_wmtwin_captcha.png

# Or in conversation
"帮我查看验证码图片"
View Session
cat /tmp/linkfox_wmtwin_sessions/13699998888.json | python3 -m json.tool
Clear Session
rm /tmp/linkfox_wmtwin_sessions/13699998888.json

Security

  • ✅ Password encrypted with RSA before transmission
  • ✅ HTTPS communication only
  • ✅ No plaintext password storage
  • ✅ Local session storage
  • ✅ Support for session cleanup

Performance

OperationTime
Password login attempt< 2s
Get CAPTCHA< 1s
Send SMS code< 2s
SMS login< 2s
API call (logged in)< 2s

Limitations

  • CAPTCHA recognition: Requires human input (no auto-recognition yet)
  • SMS verification: User must manually provide SMS code
  • Session expiry: Session may expire, requiring re-login

Competitor Search

Usage

搜索沃尔玛竞品,支持多种筛选条件。集成自动登录功能,无需手动管理登录状态。

✨ 自动分页功能

新功能:当请求的数据量大于API单页限制(50条)时,脚本会自动查询多页并合并结果:

# 自动获取100条数据(自动查询2页)
python3 scripts/wmtwin_search_competitors.py \
    --keyword "iphone case" \
    --phone 15625238480 \
    --page-size 100 \
    -o results.json

特性:

  • ✅ 自动检测请求数量是否超过单页限制(50条)
  • ✅ 自动查询多页直到达到目标数量
  • ✅ 自动合并多页结果为单个JSON文件
  • ✅ 显示实时查询进度(已获取/目标总数)
  • ✅ 支持所有筛选条件
自动登录流程

调用搜索 API 时会自动:

  1. 检查是否有有效的登录 session
  2. 如果没有 session,引导用户登录
  3. 登录成功后自动保存 session
  4. 下次自动加载已保存的 session
  5. 如果 session 过期,自动重新登录
Python 代码
from scripts.wmtwin_search_competitors import WMTwinCompetitorSearch

# 创建搜索客户端(提供手机号会自动加载已有登录)
client = WMTwinCompetitorSearch(phone="13699998888")

# 方法1: 使用参数字典(自动检查登录)
params = {
    "keyword": "iphone case",
    "is_wfs": True,
    "min_sales_volume": 200,
    "max_sales_volume": 800,
    "min_sales_amount": 200,
    "max_sales_amount": 800,
    "min_number_of_reviews": 50,
    "max_number_of_reviews": 100,
    "min_average_rating": 1.0,
    "max_average_rating": 5.0,
    "min_price": 1.0,
    "max_price": 10.0,
    "seller_name": "ERIC-EXPRESS",
    "brand": "Simyoung",
    "page": 1,
    "pageSize": 10
}
results = client.search_from_params(params)

# 方法2: 直接调用(自动检查登录)
results = client.search_competitors(
    keyword="iphone case",
    is_wfs=True,
    min_sales_volume=200,
    max_sales_volume=800,
    min_sales_amount=200,
    max_sales_amount=800,
    min_number_of_reviews=50,
    max_number_of_reviews=100,
    min_average_rating=1.0,
    max_average_rating=5.0,
    min_price=1.0,
    max_price=10.0,
    seller_name="ERIC-EXPRESS",
    brand="Simyoung",
    page=1,
    page_size=10
)

# 方法3: 提供登录信息(首次登录)
results = client.search_competitors(
    keyword="iphone",
    phone="13699998888",
    password="your_password",  # 可选,不提供会提示输入
    is_wfs=True
)

# 方法4: 自动分页获取大量数据(推荐)
results = client.search_multiple_pages(
    total_count=100,  # 自动查询多页直到获取100条
    keyword="iphone case",
    phone="15625238480",
    is_wfs=True,
    min_sales_volume=200
)
print(f"共获取 {len(results['data']['list'])} 条数据")

# 使用解码后的数据
for product in results['data']['list']:
    print(f"产品: {product['title']}")
    print(f"价格: {product['price']}")
    print(f"卖家: {product['sellers'][0]['display_name']}")
    print(f"销量: {product['sales_trends'][0]['sales_volume']['label']}")
命令行
# 基本搜索(会自动检查登录,需要时提示登录)
python3 scripts/wmtwin_search_competitors.py --keyword "iphone"

# 提供手机号(自动加载已有登录)
python3 scripts/wmtwin_search_competitors.py --keyword "iphone" --phone 13699998888

# 完整参数(自动管理登录)
python3 scripts/wmtwin_search_competitors.py \
    --keyword "iphone case" \
    --phone 13699998888 \
    --seller-name "ERIC-EXPRESS" \
    --brand "Simyoung" \
    --is-wfs \
    --min-sales 200 \
    --max-sales 800 \
    --min-sales-amount 200 \
    --max-sales-amount 800 \
    --min-reviews 50 \
    --max-reviews 100 \
    --min-rating 1.0 \
    --max-rating 5.0 \
    --min-price 1.0 \
    --max-price 10.0 \
    --page 1 \
    --page-size 10

# 模拟模式(无需登录,用于测试)
python3 scripts/wmtwin_search_competitors.py --keyword "iphone" --mock

# 从 JSON 文件读取参数
python3 scripts/wmtwin_search_competitors.py --from-json params.json --phone 13699998888

# 保存结果(自动保存原始和解码两个文件)
python3 scripts/wmtwin_search_competitors.py --keyword "iphone" --phone 13699998888 -o results.json
# 这将保存:
#   - results_raw.json (原始编码数据)
#   - results.json (解码后的数据)

重要说明:

  • 当使用 -o 参数保存文件时,会自动保存两个文件:
    • <filename>_raw.json - 原始编码数据(API直接返回的数据)
    • <filename>.json - 解码后的数据(所有字符已解码)
  • 后续操作始终使用解码后的文件
  • 解码过程自动进行,无需手动操作
搜索参数
参数名类型必填说明示例
keywordstring是搜索关键词"iphone"
is_wfsboolean否只搜索 WFS 商品true
min_sales_volumeinteger否最小销量4000
max_sales_volumeinteger否最大销量90000
min_sales_amountinteger否最小销售额200
max_sales_amountinteger否最大销售额800
min_number_of_reviewsinteger否最小评论数50
max_number_of_reviewsinteger否最大评论数100
min_average_ratingfloat否最低评分(1-5)1.0
max_average_ratingfloat否最高评分(1-5)5.0
min_pricefloat否最低价格1.0
max_pricefloat否最高价格10.0
seller_namestring否卖家名称"ERIC-EXPRESS"
brandstring否品牌"Simyoung"
pageinteger否页码(从1开始)1
pageSizeinteger否每页数量10
返回数据结构

返回的数据结构与登录后调用其他 API 相同,包含产品列表、卖家信息、销售数据等。所有编码字符会自动解码。

详细数据结构和字段说明见 references/competitor_search.md。

自动解码

沃师傅使用 Unicode 字符编码数据,本工具会自动解码:

编码示例(码点)解码结果类型
U+021F…(卖家名)ERIC-EXPRESS卖家名称
U+0212 U+0213…$12.37价格
U+0213 U+0211 U+0211 +200+数量
U+0213 U+0212…$2110.4k+销售额
常见用法示例
# 1. 搜索高销量产品
results = client.search_competitors(
    keyword="phone case",
    min_sales_volume=10000,
    page_size=50
)

# 2. 只搜索 WFS 商品
results = client.search_competitors(
    keyword="iphone",
    is_wfs=True
)

# 3. 特定销量区间
results = client.search_competitors(
    keyword="charger",
    min_sales_volume=5000,
    max_sales_volume=50000
)

# 4. 按评论数和评分筛选
results = client.search_competitors(
    keyword="iphone case",
    min_number_of_reviews=50,
    max_number_of_reviews=100,
    min_average_rating=4.0,
    max_average_rating=5.0
)

# 5. 按价格范围筛选
results = client.search_competitors(
    keyword="phone charger",
    min_price=5.0,
    max_price=20.0
)

# 6. 按卖家和品牌筛选
results = client.search_competitors(
    keyword="iphone case",
    seller_name="ERIC-EXPRESS",
    brand="Simyoung"
)

# 7. 综合筛选(多条件组合)
results = client.search_competitors(
    keyword="iphone case",
    is_wfs=True,
    min_sales_volume=200,
    max_sales_volume=800,
    min_price=1.0,
    max_price=10.0,
    min_number_of_reviews=50,
    max_number_of_reviews=100,
    min_average_rating=1.0,
    max_average_rating=5.0,
    seller_name="ERIC-EXPRESS",
    brand="Simyoung",
    page=1,
    page_size=10
)

# 8. 分页获取所有数据
all_products = []
page = 1
while True:
    results = client.search_competitors(
        keyword="iphone",
        page=page,
        page_size=50
    )
    products = results['data']['list']
    if not products:
        break
    all_products.extend(products)
    page += 1
命令行用法示例
# 基本搜索
python3 scripts/wmtwin_search_competitors.py --keyword "iphone case" --phone 15625238480

# 多条件筛选
python3 scripts/wmtwin_search_competitors.py \
    --keyword "iphone case" \
    --phone 15625238480 \
    --seller-name "ERIC-EXPRESS" \
    --brand "Simyoung" \
    --is-wfs \
    --min-sales 200 \
    --max-sales 800 \
    --min-sales-amount 200 \
    --max-sales-amount 800 \
    --min-reviews 50 \
    --max-reviews 100 \
    --min-rating 1.0 \
    --max-rating 5.0 \
    --min-price 1.0 \
    --max-price 10.0 \
    --page 1 \
    --page-size 10 \
    -o results.json

References

  • API Documentation: See references/api.md
  • Competitor Search API: See references/competitor_search.md
  • Auto Login Guide: See AUTO_LOGIN.md
  • Competitor Search Quick Start: See COMPETITOR_SEARCH.md
  • Login Script: See scripts/wmtwin_login.py
  • Search Script (with Auto Login): See scripts/wmtwin_search_competitors.py
  • Decoder: See scripts/wmtwin_complete_decoder.py
  • Decoding Guide: See DECODING.md
  • Auto Paging: See AUTO_PAGING.md

Handling Large Responses

To avoid overflowing the agent context, persist the response to disk and extract only the fields you need:

python scripts/response_io.py run --script scripts/wmtwin_complete_decoder.py --out-dir <DIR> '<params>'
python scripts/response_io.py read <file> --fields "<paths>"   # or --path "<JMESPath>"

Pick --out-dir outside any git working tree (e.g. /tmp/... on Unix, %TEMP%/... on Windows). Persisted responses may contain PII, pricing, or auth-sensitive data — do not commit them. Files are not auto-deleted; clean up when the task is done.

This skill exposes multiple entry scripts: wmtwin_complete_decoder.py, wmtwin_login.py, wmtwin_search_competitors.py. Pass --script scripts/<name>.py to choose the one you need.

run writes the full response to a file and emits only a schema preview + file path. read projects specific fields, with --limit/--offset for slicing and --format json|jsonl|csv|table for output.

When to prefer this pattern — apply your judgment based on the response characteristics, e.g.:

  • High field count per record, or fields you don't need
  • Batch/paginated results (multiple items per call)
  • Long-text fields (descriptions, reviews, HTML, time series)
  • Output reused across later steps rather than consumed immediately

For small, single-use responses, calling the main script directly is fine.

⚠️ The preview is a truncated schema + sample, not the full data. Any field-level decision must read from the persisted file via read.

Comments

Markdown supported