个体工商户版批量上传 接口破解
发布于 4 年前 作者 lei04 1553 次浏览 来自 分享

本人是个体户,所以可以网页上传商品到草稿状态

一直期待着开放对个体工商户的API,奈何迟迟不来,只能自己开发一版:

工具:python3 + selenium

思路如下

第一步 先把需要上传的图片全部上传到腾讯 并记录其返回到code 与所属spu对应 主要包含三类图片注意区分:

主图(最多九张) 详图(最多九张) 属性图(张数不限制)

第二步 将整理好的json以{data: data}的形式以form表单格式上传到微信端 ---- 草稿状态的SPU完成 稍作修改就可以轻松上架了

from selenium import webdriver
import ssl
import mysql.connector
from requests_toolbelt.multipart.encoder import MultipartEncoder
import random
import time
from urllib import parse
import re
import json
import requests
import urllib.request

price = re.compile('[0-9]+')

ssl._create_default_https_context = ssl._create_unverified_context
chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
# chrome_options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片, 提升速度
client = webdriver.Chrome(chrome_options=chrome_options)
client.maximize_window()
client.implicitly_wait(3)

# 登陆微信小商店首页
client.get('https://shop.weixin.qq.com/')

# 写入本地数据库
conn = mysql.connector.connect(
    host="",  # 数据库主机地址
    user="",  # 数据库用户名
    password="",  # 数据库密码
    database="",
    auth_plugin='mysql_native_password',
    use_unicode=True)
cursor = conn.cursor()
sql = 'SELECT sd.spu_id, sd.main_img, sd.price, sd.attr_list, sd.attr_imgs, sd.main_imgs, sd.detail_imgs, sd.data_desc from spu_detail sd where not EXISTS(SELECT spu_id from spu_upped su where su.status = 1 and su.spu_id = sd.spu_id)'
cursor.execute(sql)
fetchall = cursor.fetchall()

def get_price(data):
    if price.findall(data):
        return int(int(price.findall(data)[-1]) * 1.2 + 6)
    else:
        return False

def download_img(url):
    opener = urllib.request.build_opener()
    opener.addheaders = [('user-agent',
                          'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36')]
    urllib.request.install_opener(opener)
    urllib.request.urlretrieve(url, 'download.jpg')
    return upload_img('download.jpg')

# 上传图片返回数据
def upload_img(tmp_file):
    token = get_para(client.current_url, 'token')
    client.get_cookies()
    ticket_current = client.execute_script("return window.__INITIAL_STATE__.userInfo.mediaTicket")
    ticket = f'ticket_id=gh_8b58b7d45703&ticket={ticket_current}'
    upload_url = f'https://mp.weixin.qq.com/cgi-bin/filetransfer?action=preview&f=json&{ticket}&token={token}&lang=zh_CN'
    cookie = ';'.join(list(map(lambda x: x['name'] + '=' + x['value'], client.get_cookies())))
    multipart_encoder = MultipartEncoder(
        fields={
            'file': ('download.jpg', open(tmp_file, 'rb'), 'image/jpeg'),
        }
    )
    len = multipart_encoder.len
    content_type = multipart_encoder.content_type
    headers = {
        'authority': 'mp.weixin.qq.com',
        'method': 'POST',
        'scheme': 'https',
        'content-length': f'{len}',
        'pragma': 'no-cache',
        'accept': 'application/json, text/plain, */*',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'no-cache',
        'content-type': content_type,
        'cookie': cookie,
        'origin': 'https://mp.weixin.qq.com',
        'referer': f'https://mp.weixin.qq.com/wxatrade/goods/entry?catId=6839&brandId=2100000000&token={token}&lang=zh_CN',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest'
    }

    headers['Content-Type'] = content_type
    # 请求头必须包含一个特殊的头信息,类似于Content-Type: multipart/form-data; boundary=${bound}
    # 注意:这里请求头也可以自己设置Content-Type信息,用于自定义boundary
    r = requests.post(upload_url, data=multipart_encoder, headers=headers)
    res = json.loads(r.text)
    print(r.text)
    return res['content']

def get_up_data(headImg, detailImg, desc, products_sku):
    false, true, null = 'false', 'true', None
    return {
        "product": {
            "productKey": {},
            "info": {
                "title": "待完善",
                "model": "",
                "subTitle": "待完善",
                "headImg": headImg,
                "detail": {
                    "detailImg": detailImg
                },
                "param": [],
                "expressInfo": {
                    "templateId": "2049928"
                },
                "serviceDesc": {
                    "desc": desc
                },
                "qualificationUrl": [],
                "brandId": "2100000000",
                "category": [
                    {
                        "catId": "6831",
                        "name": "箱包皮具",
                        "fCatId": "0",
                        "createTime": "1588338821",
                        "updateTime": "1594184186",
                        "catType": 1,
                        "version": 0,
                        "bizuin": "0",
                        "brandCat": "9223372036854775807",
                        "catInfo": {
                            "catLevel": 1,
                            "highestPriceFixing": 250000,
                            "isRequired": 0,
                            "isCustomize": 0,
                            "specType": 0,
                            "specTypeDesc": "",
                            "attrTemplateId": "0",
                            "attrTemplateName": "",
                            "maxAttrNum": 0,
                            "editByUser": 0,
                            "wording": "",
                            "description": "",
                            "maxProductNum": 0,
                            "qualification": "",
                            "productQualification": "",
                            "quaNeedAudit": "",
                            "maxQualificationImg": 0,
                            "catGroup": 4294967295,
                            "qualificationId": "0",
                            "qualificationType": 0,
                            "productQualificationType": 0,
                            "productQualificationId": "0",
                            "isVirtualGoods": false
                        },
                        "auditId": "0",
                        "desc": "",
                        "priority": 0
                    }, {
                        "catId": "6843",
                        "name": "潮流女包",
                        "fCatId": "6831",
                        "createTime": "1588338821",
                        "updateTime": "1594184156",
                        "catType": 1,
                        "version": 0,
                        "bizuin": "0",
                        "brandCat": "9223372036854775807",
                        "catInfo": {
                            "catLevel": 2,
                            "highestPriceFixing": 250000,
                            "isRequired": 0,
                            "isCustomize": 0,
                            "specType": 0,
                            "specTypeDesc": "",
                            "attrTemplateId": "0",
                            "attrTemplateName": "",
                            "maxAttrNum": 0,
                            "editByUser": 0,
                            "wording": "",
                            "description": "",
                            "maxProductNum": 0,
                            "qualification": "",
                            "productQualification": "",
                            "quaNeedAudit": "",
                            "maxQualificationImg": 0,
                            "catGroup": 4294967295,
                            "qualificationId": "0",
                            "qualificationType": 0,
                            "productQualificationType": 0,
                            "productQualificationId": "0",
                            "isVirtualGoods": false
                        },
                        "auditId": "0",
                        "desc": "",
                        "priority": 0
                    }, {
                        "catId": "6851",
                        "name": "特殊商品",
                        "fCatId": "6843",
                        "createTime": "1588338821",
                        "updateTime": "1599221665",
                        "catType": 1,
                        "version": 0,
                        "bizuin": "0",
                        "brandCat": "9223372036854775807",
                        "catInfo": {
                            "maxAttrNum": 28,
                            "catLevel": 3,
                            "highestPriceFixing": 250000,
                            "maxQualificationImg": 0,
                            "enterpriseAuditInfo": {
                                "qualificationType": 0,
                                "productQualificationType": 0,
                                "qualification": "",
                                "productQualification": "",
                                "quaNeedAudit": "",
                                "maxQualificationImg": 0,
                                "qualificationId": "0",
                                "productQualificationId": "0"
                            },
                            "qualificationType": 0,
                            "productQualificationType": 0,
                            "isRequired": 0,
                            "isCustomize": 0,
                            "specType": 0,
                            "specTypeDesc": "",
                            "attrTemplateId": "0",
                            "attrTemplateName": "",
                            "editByUser": 0,
                            "wording": "",
                            "description": "",
                            "maxProductNum": 0,
                            "qualification": "",
                            "productQualification": "",
                            "quaNeedAudit": "",
                            "catGroup": 4294967295,
                            "qualificationId": "0",
                            "productQualificationId": "0",
                            "isVirtualGoods": false
                        },
                        "auditId": "0",
                        "desc": "",
                        "priority": 0
                    }],
                "shopcatId": []
            },
            "productSkus": products_sku
        },
        "type": 1,
        "listingFlag": false
    }

catId = 1603702999999

def get_product_sku(index, color, image_key, spu_price, spu_id):
    false, true, null = 'false', 'true', None
    global catId
    catId = catId - 1
    return {
        "__skuKey": f"134923.{catId}",
        "__skuTitle": color,
        "__skuSelected": true,
        "__selectedKey": index,
        "productSkuInfo": {
            "thumbImg": image_key,
            "salePrice": spu_price,
            "skuCode": spu_id,
            "stockInfo": {
                "stockNum": 10
            },
            "saleParam": [{
                "categorys": [{
                    "thumbImg": "",
                    "desc": "",
                    "catId": "134923",
                    "name": "选择颜色",
                    "fCatId": "6851",
                    "createTime": "1589356824",
                    "updateTime": "1589356824",
                    "catType": 3,
                    "version": 0,
                    "bizuin": "0",
                    "brandCat": "0",
                    "catInfo": {
                        "isCustomize": 1,
                        "highestPriceFixing": 250000,
                        "isRequired": 0,
                        "specType": 0,
                        "specTypeDesc": "",
                        "attrTemplateId": "0",
                        "attrTemplateName": "",
                        "maxAttrNum": 0,
                        "editByUser": 0,
                        "catLevel": 0,
                        "wording": "",
                        "description": "",
                        "maxProductNum": 0,
                        "qualification": "",
                        "productQualification": "",
                        "quaNeedAudit": "",
                        "maxQualificationImg": 0,
                        "catGroup": 4294967295,
                        "qualificationId": "0",
                        "qualificationType": 0,
                        "productQualificationType": 0,
                        "productQualificationId": "0",
                        "isVirtualGoods": false
                    },
                    "auditId": "0",
                    "priority": 0,
                    "maxLevel": 2
                }, {
                    "fCatId": "134923",
                    "catId": catId,
                    "name": color,
                    "desc": "有什么疑问可以联系客服",
                    "catInfo": {
                        "editByUser": 1
                    },
                    "priority": index + 1,
                    "selected": true,
                    "thumbImg": image_key
                }]
            }]
        }
    }

def draft_spu(item):
    spu_id = item[0]  # 无需处理
    attr_imgs = json.loads(item[4])
    main_imgs = get_9pic(json.loads(item[5]))
    detail_imgs = get_9pic(json.loads(item[6]))
    attr_imgs_big = []
    for index, attr in enumerate(attr_imgs):
        url = attr_imgs[index].replace('310x310', '750x750')
        attr_imgs_big.append(url)
    main_img_arr = list(map(lambda x: download_img(x), main_imgs))
    detail_img_arr = list(map(lambda x: download_img(x), detail_imgs))
    product_sku_arr = list(map(lambda x: download_img(x), attr_imgs_big))
    cursor.execute(
        f'''insert into spu_img_key (spu_id, product_sku_arr, main_img_arr, detail_img_arr) values ('{spu_id}', '{json.dumps(product_sku_arr)}', '{json.dumps(main_img_arr)}', '{json.dumps(detail_img_arr)}')''')

def get_para(url, param):
    params = parse.parse_qs(parse.urlparse(url).query)
    return params[param][0]

def get_9pic(items):
    if len(items) <= 9:
        return items
    else:
        return items[0: 9]

def refresh_client():
    client.refresh()
    time.sleep(3)

print('暂停点')

for index, item in enumerate(fetchall):
    try:
        if index != 0 and index % 10 == 0:
            refresh_client()
        draft_spu(item)
        cursor.execute(f'''insert into spu_upped (spu_id) values ('{item[0]}')''')
        conn.commit()
    except:
        pass

client.quit()

1 回复
回到顶部