微店关键词搜索接口接入与系统对接指南

Source
一、接口权限确认与准备
  1. 确认接口权限
    • 登录开放平台,进入「​​​文档​​​」→「接口权限」→ 搜索「关键词搜索接口」(通常为 item.search)。
    • 若未开通,需提交权限申请,需填写用途说明(如“用于本站商品搜索功能”)。
  2. 获取接口参数
    • 根据文档确认必选参数:
method: item.search  
keyword: 搜索关键词  
page_no: 分页页码  
page_size: 每页数量

• 其他可选参数:价格区间(​​start_price​​/​​end_price​​)、排序方式(​​sort_by​​)等。

二、签名认证与请求构造

微店API使用AppKey签名认证,需按规则生成签名(​​sign​​)。

1.签名生成步骤
参数排序:将所有请求参数按字母升序排列(排除​​sign​​自身)。
拼接字符串:格式为 ​​key1=value1&key2=value2​​(需URL编码)。
加密签名:使用 ​​HMAC-SHA256​​ 算法,以 ​​App Secret​​ 为密钥加密。
Python签名示例

import hmac  
import urllib.parse  
from hashlib import sha256  

def generate_sign(params, app_secret):  
    # 1. 参数排序  
    sorted_params = sorted(params.items(), key=lambda x: x[0])  
    # 2. 拼接字符串  
    query_str = '&'.join([f'{k}={urllib.parse.quote_plus(str(v))}' for k, v in sorted_params])  
    # 3. HMAC-SHA256加密  
    sign = hmac.new(app_secret.encode(), query_str.encode(), sha256).hexdigest()  
    return sign.upper()  # 微店要求大写

2.构造完整请求

import requests  

def search_weidian_items(keyword, page=1, page_size=20):  
    app_key = "YOUR_APP_KEY"  
    app_secret = "YOUR_APP_SECRET"  
    url = "https://api.weidian.com/router"  

    # 基础参数  
    params = {  
        "method": "item.search",  
        "app_key": app_key,  
        "keyword": keyword,  
        "page_no": page,  
        "page_size": page_size,  
        "timestamp": int(time.time() * 1000)  # 毫秒级时间戳  
    }  

    # 生成签名  
    sign = generate_sign(params, app_secret)  
    params["sign"] = sign  

    # 发送请求  
    response = requests.get(url, params=params)  
    if response.status_code == 200:  
        return response.json()  
    else:  
        raise Exception(f"API请求失败: {response.text}")
三、数据解析与系统对接

1.字段映射与存储
• 解析接口返回的JSON数据,提取关键字段并映射到本地数据库:

# 示例:解析商品数据  
def parse_items(response_data):  
    items = []  
    for item in response_data.get("result", {}).get("items", []):  
        mapped_item = {  
            "product_id": item["num_iid"],  
            "title": item["title"],  
            "price": float(item["price"]),  
            "image_url": item["image_url"],  
            "seller_id": item["seller_id"],  
            "category": item["category_name"]  
        }  
        items.append(mapped_item)  
    return items  

# 存储到MySQL  
def save_to_database(items):  
    with mysql.connector.connect() as db:  
        cursor = db.cursor()  
        sql = """  
            INSERT INTO products  
            (product_id, title, price, image_url, seller_id, category)  
            VALUES (%s, %s, %s, %s, %s, %s)  
            ON DUPLICATE KEY UPDATE price=VALUES(price)  
        """  
        for item in items:  
            cursor.execute(sql, (  
                item["product_id"],  
                item["title"],  
                item["price"],  
                item["image_url"],  
                item["seller_id"],  
                item["category"]  
            ))  
        db.commit()

2.分页与全量同步
• 循环调用直到无更多数据:

def sync_all_items(keyword):  
    page = 1  
    while True:  
        data = search_weidian_items(keyword, page=page)  
        items = parse_items(data)  
        if not items:  
            break  
        save_to_database(items)  
        if data["result"]["has_next"]:  
            page += 1  
        else:  
            break
四、系统集成实战场景

场景:搭建商品搜索中台

1.前端搜索页面

<!-- 搜索框 -->  
<input type="text" id="searchInput" placeholder="输入商品关键词">  
<button onclick="searchItems()">搜索</button>  

<!-- 结果展示 -->  
<div id="results"></div>  

<script>  
async function searchItems() {  
    const keyword = document.getElementById('searchInput').value;  
    const response = await fetch(`/api/search?keyword=${encodeURIComponent(keyword)}`);  
    const data = await response.json();  
    renderResults(data.items);  
}  

function renderResults(items) {  
    const html = items.map(item => `  
        <div class="item">  
            <img src="${item.image_url}" />  
            <h3>${item.title}</h3>  
            <p>价格:¥${item.price}</p>  
        </div>  
    `).join('');  
    document.getElementById('results').innerHTML = html;  
}  
</script>

2.后端API路由(Node.js示例)

const express = require('express');  
const router = express.Router();  
const { search_weidian_items } = require('./weidian_api');  

router.get('/api/search', async (req, res) => {  
    try {  
        const { keyword } = req.query;  
        const data = await search_weidian_items(keyword);  
        res.json({ items: data.result.items });  
    } catch (error) {  
        res.status(500).json({ error: '搜索失败' });  
    }  
});
五、安全与性能优化

1.防止高频调用
• 使用令牌桶算法限制用户搜索频率:

from flask_limiter import Limiter  
from flask_limiter.util import get_remote_address  

limiter = Limiter(app, key_func=get_remote_address)  
@app.route('/api/search')  
@limiter.limit("10/minute")  # 每分钟最多10次  
def search_api():  
    # ...

2.缓存热门关键词
• 对高频搜索词结果缓存1小时:

import redis  
r = redis.Redis()  

def get_cached_search(keyword):  
    cache_key = f"search:{keyword}"  
    cached = r.get(cache_key)  
    if cached:  
        return json.loads(cached)  
    data = search_weidian_items(keyword)  
    r.setex(cache_key, 3600, json.dumps(data))  # 缓存1小时  
    return data
六、常见问题处理

1.返回“无效签名”错误
• 检查项:
◦ 时间戳是否为毫秒级(需13位数字)。
◦ 参数是否按字母升序排列。
◦ ​​App Secret​​是否与平台显示一致。

2.搜索词包含特殊字符
• 使用URL编码处理关键词:

keyword = urllib.parse.quote_plus("手机/电脑")

3.高并发场景优化
• 使用异步任务队列(如Celery)处理搜索请求:

@celery.task  
def async_search(keyword):  
    return search_weidian_items(keyword)  

# 前端轮询任务结果  
task = async_search.delay(keyword)  
result = task.get(timeout=30)
七、高级功能扩展

1.结合NLP增强搜索
• 在调用微店API前,对用户输入进行分词和意图识别:

import jieba  
from text_analysis import extract_keywords  

def preprocess_query(query):  
    # 分词与去停用词  
    words = jieba.lcut(query)  
    keywords = extract_keywords(words)  
    return ' '.join(keywords)

2.数据聚合展示
• 整合微店与其他平台(如淘宝、京东)的搜索结果:

def multi_platform_search(keyword):  
    weidian = search_weidian_items(keyword)  
    taobao = search_taobao_items(keyword)  
    return merge_results(weidian, taobao)

通过以上步骤,可快速将微店关键词搜索能力对接到自有系统。重点关注数据一致性(定期同步更新价格库存)、搜索体验优化(智能推荐、纠错)及安全防护(防爬虫、参数校验)。