更新 README + 模板导出新增面料弹性/沙特阿拉伯码识别
1) README 重写:双模式架构(热点采集/Pinterest 参考模式)、模特性别分组、生图尺寸配置、模板导出增强、一键打包脚本 2) template_export:识别「面料弹性」列填 spu.fabric;识别「尺码表-沙特阿拉伯码」列填 sku.size(均模糊匹配,检测到才填)
This commit is contained in:
@@ -205,8 +205,10 @@ def _fill_design_fields(router, spu_code: str, oss_code: str, cn_title: str, en_
|
||||
|
||||
|
||||
def _build_spu_row(spu: Dict[str, Any], spu_code: str, origin_province: str,
|
||||
color: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""构造一行 SPU(固定字段:SKC货号=code、风格=休闲、商品产地=经营站点;多颜色时用色值列区分)。"""
|
||||
color: Optional[str] = None,
|
||||
fabric_headers: Optional[List[str]] = None) -> Dict[str, Any]:
|
||||
"""构造一行 SPU(固定字段:SKC货号=code、风格=休闲、商品产地=经营站点;多颜色时用色值列区分)。
|
||||
fabric 填「面料弹性」列(fabric_headers,如 SPU商品属性-面料弹性,检测到才填 spu.fabric)。"""
|
||||
row: Dict[str, Any] = {
|
||||
"基础信息-商品层级": "spu",
|
||||
"SKC货号": spu_code, # code 路由为 SKC货号(用户要求)
|
||||
@@ -220,6 +222,10 @@ def _build_spu_row(spu: Dict[str, Any], spu_code: str, origin_province: str,
|
||||
v = spu.get(dbk)
|
||||
if v not in (None, ""):
|
||||
row[header] = v
|
||||
fabric = spu.get("fabric")
|
||||
if fabric not in (None, "") and fabric_headers:
|
||||
for h in fabric_headers:
|
||||
row[h] = fabric
|
||||
return row
|
||||
|
||||
|
||||
@@ -235,14 +241,26 @@ def _find_bust_headers(router) -> List[str]:
|
||||
return hits or ["胸围全围(cm)"]
|
||||
|
||||
|
||||
def _find_fabric_headers(router) -> List[str]:
|
||||
"""定位所有「面料弹性」列(SPU商品属性-面料弹性…模糊匹配);匹配到多个时全部填 spu.fabric。"""
|
||||
return [str(k) for k in router.column_map if "面料弹性" in str(k)]
|
||||
|
||||
|
||||
def _find_sa_size_headers(router) -> List[str]:
|
||||
"""定位所有「沙特阿拉伯码」列(尺码表-沙特阿拉伯码…模糊匹配);匹配到多个时全部填 sku.size。"""
|
||||
return [str(k) for k in router.column_map if "沙特阿拉伯码" in str(k)]
|
||||
|
||||
|
||||
def _build_sku_row(spu_code: str, sc: str, sk: Dict[str, Any], size: str, color: str,
|
||||
warehouses: List[str], markup_percent: float = 0.0,
|
||||
multi: bool = True, price_header: str = "申报价格-日本站",
|
||||
bust_headers: Optional[List[str]] = None,
|
||||
price_headers: Optional[List[str]] = None) -> Dict[str, Any]:
|
||||
price_headers: Optional[List[str]] = None,
|
||||
sa_size_headers: Optional[List[str]] = None) -> Dict[str, Any]:
|
||||
"""构造一行 SKU(固定字段:SPU货号、SKC货号=sku.code、规格类型2、币种 CNY、发货仓1~N 及库存 200)。
|
||||
价格(price_headers 列,如 申报价格-美国站/日本站,模糊匹配到多个时全部填)= SKU.price × (1+markup/100),
|
||||
预先填好。bust 填所有「胸围」列(bust_headers,如 基码表-胸围(cm)/胸围全围(cm),检测到才填)。
|
||||
size 填「尺码」列 + 所有「沙特阿拉伯码」列(sa_size_headers,如 尺码表-沙特阿拉伯码,检测到才填)。
|
||||
规格类型2 统一填「尺码」两个字(不是 size 参数值)。"""
|
||||
row: Dict[str, Any] = {
|
||||
"基础信息-商品层级": "sku",
|
||||
@@ -256,6 +274,8 @@ def _build_sku_row(spu_code: str, sc: str, sk: Dict[str, Any], size: str, color:
|
||||
price_headers = [price_header]
|
||||
if bust_headers is None:
|
||||
bust_headers = ["胸围全围(cm)"]
|
||||
if sa_size_headers is None:
|
||||
sa_size_headers = []
|
||||
for j, w in enumerate(warehouses, start=1):
|
||||
row[f"发货仓{j}"] = w
|
||||
row[f"发货仓{j}库存"] = 200
|
||||
@@ -276,6 +296,13 @@ def _build_sku_row(spu_code: str, sc: str, sk: Dict[str, Any], size: str, color:
|
||||
for h in price_headers:
|
||||
row[h] = v
|
||||
continue
|
||||
if dbk == "size":
|
||||
if v in (None, ""):
|
||||
continue
|
||||
row[header] = v
|
||||
for h in sa_size_headers:
|
||||
row[h] = v
|
||||
continue
|
||||
if v not in (None, ""):
|
||||
row[header] = v
|
||||
return row
|
||||
@@ -416,6 +443,8 @@ def _insert_product_block(
|
||||
composite_urls: Optional[List[Dict[str, Any]]] = None,
|
||||
seed_shot_urls: Optional[List[str]] = None,
|
||||
bust_headers: Optional[List[str]] = None,
|
||||
fabric_headers: Optional[List[str]] = None,
|
||||
sa_size_headers: Optional[List[str]] = None,
|
||||
) -> List[int]:
|
||||
"""在已打开的 router 中插入一个产品的 SPU+SKU 块并填充设计字段,返回本块行号。
|
||||
|
||||
@@ -445,7 +474,7 @@ def _insert_product_block(
|
||||
# 单 SPU 多色:1 个 SPU 行(无色值,SPU 级信息由 _fill_design_fields 填充)
|
||||
# + 全部颜色尺码 SKU 行(色值在 SKU 行区分)
|
||||
block_rows.append(router.insert(
|
||||
_build_spu_row(spu, spu_code, origin_province),
|
||||
_build_spu_row(spu, spu_code, origin_province, fabric_headers=fabric_headers),
|
||||
match="exact",
|
||||
))
|
||||
for ci, (sc, skus) in enumerate(skus_by_color):
|
||||
@@ -458,7 +487,8 @@ def _insert_product_block(
|
||||
block_rows.append(router.insert(
|
||||
_build_sku_row(spu_code, sc, sk, size, color, warehouses,
|
||||
markup_percent=markup_percent, multi=True,
|
||||
bust_headers=bust_headers, price_headers=price_headers),
|
||||
bust_headers=bust_headers, price_headers=price_headers,
|
||||
sa_size_headers=sa_size_headers),
|
||||
spu_code=spu_code, match="exact",
|
||||
))
|
||||
|
||||
@@ -474,7 +504,7 @@ def _insert_product_block(
|
||||
else:
|
||||
# 单 SPU + 多颜色变体:1 个 SPU 行(无色值)+ 所有颜色所有尺码 SKU 行(色值区分)
|
||||
block_rows.append(router.insert(
|
||||
_build_spu_row(spu, spu_code, origin_province), match="exact"))
|
||||
_build_spu_row(spu, spu_code, origin_province, fabric_headers=fabric_headers), match="exact"))
|
||||
multi_variant = len(skus_by_color) > 1
|
||||
for ci, (sc, skus) in enumerate(skus_by_color):
|
||||
first = skus[0]
|
||||
@@ -484,7 +514,8 @@ def _insert_product_block(
|
||||
block_rows.append(router.insert(
|
||||
_build_sku_row(spu_code, sc, sk, size, color, warehouses,
|
||||
markup_percent=markup_percent, multi=multi_variant,
|
||||
bust_headers=bust_headers, price_headers=price_headers),
|
||||
bust_headers=bust_headers, price_headers=price_headers,
|
||||
sa_size_headers=sa_size_headers),
|
||||
))
|
||||
sku_imgs = [x for x in (images[1:] + images[:1]) if x][:4] if (ci == 0 and images) else []
|
||||
_fill_sku_carousel(router, spu_code, color, color_col, first, sku_imgs)
|
||||
@@ -551,6 +582,8 @@ def export_product(
|
||||
origin_province, warehouses = _read_meta(router)
|
||||
price_headers = _find_price_headers(router) # 申报价格列(美站/日站/英站…模糊匹配,多个全填)
|
||||
bust_headers = _find_bust_headers(router) # 胸围列(基码表-胸围(cm)/胸围全围(cm)…多个全填)
|
||||
fabric_headers = _find_fabric_headers(router) # 面料弹性列(SPU商品属性-面料弹性…检测到才填)
|
||||
sa_size_headers = _find_sa_size_headers(router) # 沙特阿拉伯码列(尺码表-沙特阿拉伯码…检测到才填)
|
||||
_insert_product_block(router, db_path, spu_code, sku_code,
|
||||
origin_province, warehouses, price_headers,
|
||||
markup_percent=markup_percent, images=images,
|
||||
@@ -559,7 +592,9 @@ def export_product(
|
||||
ja_title=ja_title, es_title=es_title,
|
||||
composite_urls=composite_urls,
|
||||
seed_shot_urls=seed_shot_urls,
|
||||
bust_headers=bust_headers)
|
||||
bust_headers=bust_headers,
|
||||
fabric_headers=fabric_headers,
|
||||
sa_size_headers=sa_size_headers)
|
||||
out = router.save(out_path)
|
||||
return Path(out)
|
||||
finally:
|
||||
@@ -591,6 +626,8 @@ def export_products(
|
||||
origin_province, warehouses = _read_meta(router)
|
||||
price_headers = _find_price_headers(router) # 申报价格列(美站/日站/英站…模糊匹配,多个全填)
|
||||
bust_headers = _find_bust_headers(router) # 胸围列(基码表-胸围(cm)/胸围全围(cm)…多个全填)
|
||||
fabric_headers = _find_fabric_headers(router) # 面料弹性列(SPU商品属性-面料弹性…检测到才填)
|
||||
sa_size_headers = _find_sa_size_headers(router) # 沙特阿拉伯码列(尺码表-沙特阿拉伯码…检测到才填)
|
||||
for r in products:
|
||||
try:
|
||||
_insert_product_block(
|
||||
@@ -608,6 +645,8 @@ def export_products(
|
||||
composite_urls=r.get("composite_urls"),
|
||||
seed_shot_urls=r.get("seed_shot_urls"),
|
||||
bust_headers=bust_headers,
|
||||
fabric_headers=fabric_headers,
|
||||
sa_size_headers=sa_size_headers,
|
||||
)
|
||||
except Exception as e: # noqa: BLE001
|
||||
print(f"[template_export] 产品 {r.get('spu_code')} 写入失败,跳过: {e}")
|
||||
|
||||
Reference in New Issue
Block a user