#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 创建500条商品数据的脚本 """ import urllib.request import urllib.error import json import random import time from datetime import datetime BASE_URL = "http://localhost:8080" AUTH_TOKEN = "Bearer 96dd2c26-8072-4a17-a449-7d302634f63a" HEADERS = { "Content-Type": "application/json", "Authorization": AUTH_TOKEN } # 已验证的真实网络图片URL(食物/零食相关) REAL_IMAGE_URLS = [ "https://images.unsplash.com/photo-1590080875515-8a3a8dc5735e?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1621939514649-280e2ee25f60?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1578985545062-69928b1d9587?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1558961363-fa8fdf82db35?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1582058091505-f87a2e55a40f?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1581793745862-99fde7fa73d2?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1622483767028-3f66f32aef97?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1566478989037-eec170784d0b?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1549007994-cb92caebd54b?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1481391319762-47dff72954d9?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1528821128474-27f963b062bf?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1606313564200-e75d5e30476c?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1622484212850-eb596d769edc?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1599599810769-bcde5a160d32?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1587132137056-bfbf0166836e?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1617374128851-c84e37dc9f37?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1559598467-f8b76c8155d0?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1509365465985-25d11c17e812?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1603569283847-aa295f0d016a?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1582281298055-e25b84a30b0b?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1599490659213-e2b9527bd087?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1559563362-c667ba5f5480?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1551024601-bec78aea704b?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1486893732792-e4f533048797?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1511381939415-e44015466834?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1606312619070-d48b4c652a52?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1601058268499-e526168d9f37?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1585225257732-537f48f9116e?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1606313564200-e75d5e30476c?w=400&h=400&fit=crop", "https://images.unsplash.com/photo-1590080875515-8a3a8dc5735e?w=400&h=400&fit=crop", ] # 按分类组织的商品数据 PRODUCT_DATA = { 1: { # 坚果炒货 "brands": ["三只松鼠", "良品铺子", "百草味", "洽洽", "来伊份", "沃隆", "楼兰蜜语", "华味亨", "松鼠集团", "坚果工坊"], "items": [ ("原味夏威夷果", ["500g", "250g", "1000g"], [39.9, 59.9, 89.9]), ("奶油味腰果", ["200g", "500g", "1000g"], [29.9, 49.9, 79.9]), ("盐焗开心果", ["300g", "500g", "150g"], [49.9, 69.9, 29.9]), ("蜂蜜核桃仁", ["250g", "500g", "100g"], [25.9, 39.9, 15.9]), ("原味瓜子", ["500g", "1000g", "200g"], [12.9, 19.9, 8.9]), ("炭烧腰果", ["200g", "500g", "100g"], [32.9, 55.9, 19.9]), ("碧根果", ["250g", "500g", "1000g"], [35.9, 59.9, 99.9]), ("巴旦木", ["300g", "500g", "150g"], [29.9, 45.9, 18.9]), ("松子", ["200g", "500g", "100g"], [59.9, 119.9, 35.9]), ("榛子", ["250g", "500g", "150g"], [39.9, 69.9, 25.9]), ("南瓜子", ["500g", "1000g", "200g"], [15.9, 25.9, 9.9]), ("杏仁", ["300g", "500g", "150g"], [32.9, 49.9, 19.9]), ("混合坚果", ["500g", "750g", "300g"], [69.9, 89.9, 45.9]), ("每日坚果", ["30包", "15包", "7包"], [99.9, 55.9, 29.9]), ("琥珀核桃", ["250g", "500g", "150g"], [22.9, 35.9, 15.9]), ("蒜香花生", ["500g", "1000g", "200g"], [9.9, 16.9, 5.9]), ("怪味胡豆", ["300g", "500g", "150g"], [12.9, 18.9, 8.9]), ("兰花豆", ["300g", "500g", "150g"], [11.9, 17.9, 7.9]), ("香酥蚕豆", ["300g", "500g", "150g"], [10.9, 16.9, 6.9]), ("青豆", ["500g", "1000g", "200g"], [14.9, 24.9, 8.9]), ] }, 2: { # 肉干果脯 "brands": ["无穷", "老四川", "周黑鸭", "绝味", "三只松鼠", "良品铺子", "百草味", "来伊份", "劲仔", "友臣"], "items": [ ("蜜汁猪肉脯", ["250g", "500g", "100g"], [29.9, 49.9, 15.9]), ("麻辣牛肉干", ["200g", "500g", "100g"], [39.9, 79.9, 22.9]), ("五香鸭脖", ["300g", "500g", "150g"], [25.9, 39.9, 15.9]), ("香辣鸡翅", ["200g", "400g", "100g"], [29.9, 49.9, 18.9]), ("鱿鱼丝", ["200g", "500g", "100g"], [22.9, 45.9, 14.9]), ("烤鱼片", ["200g", "400g", "100g"], [25.9, 45.9, 15.9]), ("手撕牛肉", ["200g", "500g", "100g"], [45.9, 99.9, 25.9]), ("卤蛋", ["10枚", "20枚", "5枚"], [15.9, 25.9, 9.9]), ("鸡爪", ["300g", "500g", "150g"], [22.9, 35.9, 13.9]), ("鸭掌", ["200g", "400g", "100g"], [25.9, 45.9, 15.9]), ("肉枣", ["300g", "500g", "150g"], [19.9, 29.9, 12.9]), ("香辣小鱼干", ["200g", "500g", "100g"], [15.9, 32.9, 9.9]), ("鱿鱼仔", ["200g", "400g", "100g"], [19.9, 35.9, 12.9]), ("墨鱼仔", ["200g", "400g", "100g"], [22.9, 39.9, 13.9]), ("卤牛肉", ["200g", "500g", "100g"], [49.9, 109.9, 28.9]), ("酱板鸭", ["半只", "整只", "1/4只"], [39.9, 69.9, 22.9]), ("腊肉", ["500g", "1000g", "250g"], [59.9, 109.9, 32.9]), ("腊肠", ["500g", "1000g", "250g"], [49.9, 89.9, 28.9]), ("肉松", ["200g", "500g", "100g"], [25.9, 49.9, 15.9]), ("鱼豆腐", ["300g", "500g", "150g"], [15.9, 23.9, 9.9]), ] }, 3: { # 糖果巧克力 "brands": ["德芙", "费列罗", "阿尔卑斯", "徐福记", "好时", "Lindt", "雀巢", "玛氏", "金帝", "明治"], "items": [ ("牛奶巧克力", ["100g", "200g", "500g"], [19.9, 35.9, 79.9]), ("黑巧克力85%", ["100g", "200g", "500g"], [29.9, 49.9, 109.9]), ("草莓味软糖", ["200g", "500g", "100g"], [12.9, 25.9, 7.9]), ("水果硬糖", ["300g", "500g", "150g"], [9.9, 14.9, 5.9]), ("棒棒糖", ["20支", "50支", "10支"], [15.9, 32.9, 8.9]), ("棉花糖", ["200g", "500g", "100g"], [11.9, 22.9, 6.9]), ("牛轧糖", ["300g", "500g", "150g"], [19.9, 29.9, 11.9]), ("太妃糖", ["200g", "500g", "100g"], [15.9, 32.9, 8.9]), ("夹心巧克力", ["150g", "300g", "500g"], [25.9, 45.9, 69.9]), ("酒心巧克力", ["150g", "300g", "500g"], [29.9, 52.9, 79.9]), ("薄荷糖", ["200g", "500g", "100g"], [9.9, 19.9, 5.9]), ("跳跳糖", ["30包", "50包", "10包"], [12.9, 18.9, 5.9]), ("橡皮糖", ["200g", "500g", "100g"], [11.9, 22.9, 6.9]), ("QQ糖", ["200g", "500g", "100g"], [10.9, 19.9, 5.9]), ("酥糖", ["300g", "500g", "150g"], [15.9, 24.9, 8.9]), ("花生糖", ["300g", "500g", "150g"], [14.9, 22.9, 8.9]), ("芝麻糖", ["300g", "500g", "150g"], [13.9, 21.9, 7.9]), ("果冻", ["500g", "1000g", "250g"], [15.9, 27.9, 8.9]), ("巧克力豆", ["200g", "500g", "100g"], [18.9, 39.9, 9.9]), ("松露巧克力", ["200g", "500g", "100g"], [35.9, 79.9, 19.9]), ] }, 4: { # 饼干糕点 "brands": ["奥利奥", "好利来", "良品铺子", "三只松鼠", "达利园", "盼盼", "康师傅", "华美", "嘉士利", "好吃点"], "items": [ ("夹心饼干", ["388g", "500g", "200g"], [19.9, 24.9, 11.9]), ("曲奇饼干", ["300g", "500g", "150g"], [22.9, 35.9, 12.9]), ("威化饼干", ["200g", "400g", "100g"], [15.9, 28.9, 8.9]), ("苏打饼干", ["500g", "1000g", "250g"], [12.9, 22.9, 7.9]), ("消化饼干", ["400g", "800g", "200g"], [15.9, 27.9, 8.9]), ("蛋黄酥", ["6枚", "12枚", "4枚"], [25.9, 45.9, 18.9]), ("凤梨酥", ["300g", "500g", "150g"], [29.9, 45.9, 16.9]), ("绿豆糕", ["300g", "500g", "150g"], [19.9, 29.9, 11.9]), ("老婆饼", ["300g", "500g", "150g"], [15.9, 24.9, 8.9]), ("麻花", ["300g", "500g", "150g"], [12.9, 19.9, 6.9]), ("沙琪玛", ["500g", "1000g", "250g"], [14.9, 25.9, 8.9]), ("蛋黄派", ["300g", "500g", "150g"], [15.9, 24.9, 8.9]), ("瑞士卷", ["300g", "500g", "150g"], [18.9, 29.9, 10.9]), ("蛋糕", ["6个装", "12个装", "3个装"], [29.9, 52.9, 16.9]), ("面包", ["500g", "1000g", "250g"], [15.9, 27.9, 8.9]), ("吐司", ["300g", "500g", "150g"], [12.9, 19.9, 6.9]), ("蛋卷", ["300g", "500g", "150g"], [19.9, 29.9, 10.9]), ("煎饼", ["300g", "500g", "150g"], [11.9, 18.9, 6.9]), ("桃酥", ["300g", "500g", "150g"], [13.9, 21.9, 7.9]), ("云片糕", ["300g", "500g", "150g"], [14.9, 22.9, 7.9]), ] }, 5: { # 蜜饯果干 "brands": ["溜溜梅", "楼兰蜜语", "良品铺子", "百草味", "来伊份", "三只松鼠", "华味亨", "好想你", "西域美农", "果园老农"], "items": [ ("芒果干", ["100g", "200g", "500g"], [12.9, 22.9, 45.9]), ("葡萄干", ["200g", "500g", "1000g"], [15.9, 29.9, 52.9]), ("草莓干", ["100g", "200g", "500g"], [18.9, 32.9, 69.9]), ("话梅", ["200g", "500g", "100g"], [14.9, 29.9, 8.9]), ("山楂片", ["300g", "500g", "150g"], [9.9, 14.9, 5.9]), ("山楂条", ["300g", "500g", "150g"], [10.9, 16.9, 5.9]), ("果脯", ["300g", "500g", "150g"], [15.9, 24.9, 8.9]), ("杏干", ["200g", "500g", "100g"], [18.9, 39.9, 10.9]), ("桃干", ["200g", "500g", "100g"], [16.9, 35.9, 9.9]), ("苹果干", ["200g", "500g", "100g"], [14.9, 29.9, 8.9]), ("香蕉片", ["200g", "500g", "100g"], [12.9, 25.9, 7.9]), ("菠萝干", ["200g", "500g", "100g"], [15.9, 32.9, 8.9]), ("猕猴桃干", ["200g", "500g", "100g"], [16.9, 34.9, 9.9]), ("柠檬干", ["100g", "200g", "50g"], [12.9, 22.9, 6.9]), ("陈皮", ["200g", "500g", "100g"], [15.9, 32.9, 8.9]), ("杨梅干", ["200g", "500g", "100g"], [17.9, 35.9, 9.9]), ("酸枣", ["200g", "500g", "100g"], [13.9, 27.9, 7.9]), ("无花果干", ["200g", "500g", "100g"], [19.9, 39.9, 10.9]), ("椰枣", ["200g", "500g", "100g"], [22.9, 45.9, 12.9]), ("蔓越莓干", ["200g", "500g", "100g"], [18.9, 37.9, 9.9]), ] }, 6: { # 饮料冲饮 "brands": ["可口可乐", "百事可乐", "农夫山泉", "汇源", "三得利", "统一", "康师傅", "香飘飘", "雀巢", "星巴克"], "items": [ ("可乐", ["330ml*6", "500ml*6", "1.5L*2"], [22.9, 28.9, 15.9]), ("雪碧", ["330ml*6", "500ml*6", "1.5L*2"], [22.9, 28.9, 15.9]), ("橙汁", ["1L", "500ml*6", "250ml*12"], [19.9, 35.9, 42.9]), ("苹果汁", ["1L", "500ml*6", "250ml*12"], [18.9, 33.9, 39.9]), ("葡萄汁", ["1L", "500ml*6", "250ml*12"], [22.9, 39.9, 45.9]), ("蜜桃乌龙茶", ["500ml*6", "1L", "300ml*6"], [25.9, 18.9, 22.9]), ("绿茶", ["500ml*6", "1L", "300ml*6"], [19.9, 15.9, 18.9]), ("红茶", ["500ml*6", "1L", "300ml*6"], [19.9, 15.9, 18.9]), ("奶茶", ["500ml*6", "1L", "300ml*6"], [25.9, 19.9, 22.9]), ("咖啡", ["250ml*6", "500ml*6", "1L"], [29.9, 45.9, 22.9]), ("豆浆", ["250ml*12", "500ml*6", "1L"], [25.9, 22.9, 12.9]), ("牛奶", ["250ml*12", "500ml*6", "1L*2"], [39.9, 35.9, 22.9]), ("酸奶", ["200g*12", "100g*16", "500g*3"], [35.9, 29.9, 25.9]), ("气泡水", ["500ml*6", "1L", "330ml*6"], [29.9, 15.9, 22.9]), ("椰子水", ["500ml*6", "1L", "330ml*6"], [35.9, 19.9, 25.9]), ("功能饮料", ["250ml*6", "500ml*6", "1L"], [29.9, 39.9, 18.9]), ("苏打水", ["500ml*6", "1L", "330ml*6"], [22.9, 12.9, 16.9]), ("蜂蜜水", ["500ml*6", "1L", "350ml*6"], [25.9, 15.9, 19.9]), ("酸梅汤", ["500ml*6", "1L", "300ml*6"], [22.9, 14.9, 17.9]), ("凉茶", ["500ml*6", "1L", "310ml*6"], [24.9, 15.9, 19.9]), ] } } def http_request(url, method="GET", data=None): """发送HTTP请求""" req = urllib.request.Request(url, method=method) for k, v in HEADERS.items(): req.add_header(k, v) if data: req.data = json.dumps(data, ensure_ascii=False).encode("utf-8") try: with urllib.request.urlopen(req, timeout=15) as resp: return json.loads(resp.read().decode("utf-8")) except urllib.error.HTTPError as e: return {"code": e.code, "message": str(e.read().decode("utf-8", errors="ignore"))} except Exception as e: return {"code": -1, "message": str(e)} def get_categories(): """获取分类列表""" url = f"{BASE_URL}/api/category/tree" data = http_request(url) if data.get("code") == 200: return data.get("data", []) print(f"获取分类失败: {data}") return [] def create_product(product_data): """创建商品""" url = f"{BASE_URL}/api/admin/product" return http_request(url, method="POST", data=product_data) def generate_sku_list(item_name, specs, prices, image_url): """生成SKU列表""" sku_list = [] for i, (spec, price) in enumerate(zip(specs, prices)): sku_name = f"{item_name.split()[0]}/{spec}" stock = random.randint(100, 2000) sku_list.append({ "skuName": sku_name, "price": round(price, 2), "stock": stock, "image": image_url, "sort": i + 1, "weight": random.randint(100, 1000) }) return sku_list def generate_products(categories, total=500): """生成商品数据""" products = [] category_ids = [c["id"] for c in categories] for i in range(total): cat_id = random.choice(category_ids) cat_data = PRODUCT_DATA.get(cat_id, PRODUCT_DATA[1]) brand = random.choice(cat_data["brands"]) item = random.choice(cat_data["items"]) item_name, specs, prices = item # 构造商品名称 prefix = random.choice(["", "精选", "进口", "网红", "手工", "传统", "", ""]) suffix = random.choice(["", " 礼盒装", " 家庭装", " 便携装", "", ""]) name = f"{prefix}{brand} {item_name}{suffix}".strip() # 随机选择图片 main_image = random.choice(REAL_IMAGE_URLS) sub_images = json.dumps([random.choice(REAL_IMAGE_URLS) for _ in range(3)]) # 生成原价(比售价略高) origin_price = round(max(prices) * random.uniform(1.1, 1.5), 2) # 生成详情HTML detail = f"""

{name}

品牌:{brand}

规格:{', '.join(specs)}

产地:{random.choice(['中国', '美国', '日本', '韩国', '泰国', '越南', '马来西亚'])}

保质期:{random.choice(['6个月', '9个月', '12个月', '18个月'])}

储存方式:{random.choice(['常温保存', '阴凉干燥处', '冷藏保存'])}

商品描述:精选优质原料,传统工艺制作,口感酥脆,回味无穷。{random.choice(['适合办公休闲', '聚会必备零食', '追剧好伴侣', '下午茶首选', '送礼佳品'])}。

""" sku_list = generate_sku_list(item_name, specs, prices, main_image) product = { "name": name, "categoryId": cat_id, "brand": brand, "mainImage": main_image, "subImages": sub_images, "detail": detail, "originPrice": origin_price, "isHot": random.choice([0, 0, 0, 1]), # 25%概率热门 "isNew": random.choice([0, 0, 0, 1]), # 25%概率新品 "status": 1, "skuList": sku_list } products.append(product) return products def main(): print("=" * 60) print("开始创建500条商品数据") print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("=" * 60) # 1. 获取分类 print("\n[1/3] 获取商品分类...") categories = get_categories() if not categories: print("获取分类失败,退出") return print(f"获取到 {len(categories)} 个分类: {[c['name'] for c in categories]}") # 2. 生成商品数据 print("\n[2/3] 生成500条商品数据...") products = generate_products(categories, 500) print(f"已生成 {len(products)} 条商品数据") # 3. 创建商品 print("\n[3/3] 开始调用接口创建商品...") success = 0 failed = 0 errors = [] for idx, product in enumerate(products, 1): try: result = create_product(product) if result.get("code") == 200: success += 1 print(f"[{idx}/500] ✓ 创建成功: {product['name'][:30]}... (ID: {result.get('data')})") else: failed += 1 errors.append({"index": idx, "name": product["name"], "error": result}) print(f"[{idx}/500] ✗ 创建失败: {product['name'][:30]}... - {result.get('message')}") except Exception as e: failed += 1 errors.append({"index": idx, "name": product["name"], "error": str(e)}) print(f"[{idx}/500] ✗ 异常: {product['name'][:30]}... - {e}") # 适当延迟,避免请求过快 if idx % 10 == 0: time.sleep(0.5) print("\n" + "=" * 60) print("执行结果统计") print("=" * 60) print(f"总计: 500") print(f"成功: {success}") print(f"失败: {failed}") print(f"成功率: {success / 500 * 100:.2f}%") if errors: print(f"\n前10条错误详情:") for err in errors[:10]: print(f" [{err['index']}] {err['name'][:40]}: {err['error']}") print("\n" + "=" * 60) print(f"完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("=" * 60) if __name__ == "__main__": main()