Files

92 lines
4.3 KiB
Python
Raw Permalink Normal View History

import csv
import importlib.util
import sys
import tempfile
import unittest
from pathlib import Path
from xml.sax.saxutils import escape
from zipfile import ZIP_DEFLATED, ZipFile
MODULE_PATH = Path(__file__).with_name("export_thirdparty_catalog_xlsx.py")
SPEC = importlib.util.spec_from_file_location("thirdparty_export", MODULE_PATH)
assert SPEC and SPEC.loader
catalog = importlib.util.module_from_spec(SPEC)
sys.modules[SPEC.name] = catalog
SPEC.loader.exec_module(catalog)
HEADERS = [
"Parent SKU", "产品标题", "sku", "变种属性名称一", "变种属性名称二",
"变种属性值一", "变种属性值二", "主图(URL)地址", "来源URL", "店铺名",
"产品id", "更新时间",
]
def inline_cell(column, row, value):
return f'<c r="{column}{row}" t="inlineStr"><is><t>{escape(value)}</t></is></c>'
def make_xlsx(path, data_rows):
rows = []
for row_number, values in enumerate([HEADERS, *data_rows], start=1):
cells = "".join(inline_cell(chr(65 + index), row_number, value) for index, value in enumerate(values))
rows.append(f'<row r="{row_number}">{cells}</row>')
worksheet = (
'<?xml version="1.0" encoding="UTF-8"?>'
'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'
'<dimension ref="A1"/><sheetData>' + "".join(rows) + '</sheetData></worksheet>'
)
with ZipFile(path, "w", ZIP_DEFLATED) as archive:
archive.writestr("xl/worksheets/sheet1.xml", worksheet)
class ThirdPartyCatalogExportTest(unittest.TestCase):
def make_source(self, rows):
temp = tempfile.TemporaryDirectory()
root = Path(temp.name) / "source"
source = root / "pinduoduo 域名" / "sample.xlsx"
source.parent.mkdir(parents=True)
make_xlsx(source, rows)
self.addCleanup(temp.cleanup)
return root, source, Path(temp.name) / "output"
def test_错误_dimension_仍导出完整数据和规范_pdd_url(self):
root, source, output = self.make_source([
["MAIN", "标题", "SKU-A", "颜色分类", "尺码", "黑色", "M", "https://img.example/a.jpg", "https://mobile.pinduoduo.com/goods.html?goods_id=123456789&track=1", "店铺 A", "24948397488", "2026-08-19"],
["MAIN", "标题", "SKU-B", "尺碼", "顏色", "L", "白色", "https://img.example/a.jpg", "https://mobile.yangkeduo.com/goods.html?goods_id=987654321", "店铺 A", "24948397488", "2026-08-19"],
])
result = catalog.export_file(source, root, output)
self.assertEqual((result.rows, result.valid_pdd_rows), (2, 2))
with result.output.open(encoding="utf-8-sig", newline="") as handle:
exported = list(csv.DictReader(handle))
self.assertEqual(len(exported), 2)
self.assertEqual(exported[0]["pdd_goods_url"], "https://mobile.yangkeduo.com/goods.html?goods_id=123456789")
self.assertEqual((exported[0]["color"], exported[0]["size"], exported[0]["parse_ok"]), ("黑色", "M", "true"))
self.assertEqual((exported[1]["color"], exported[1]["size"]), ("白色", "L"))
self.assertEqual(exported[0]["source_file"], "pinduoduo 域名/sample.xlsx")
def test_无效_pdd_url_保留蝦皮字段但不创建关联(self):
root, source, output = self.make_source([
["MAIN", "标题", "SKU-A", "款式", "套餐", "甲", "乙", "https://img.example/a.jpg", "https://example.com/item", "店铺 A", "24948397488", ""],
])
result = catalog.export_file(source, root, output)
self.assertEqual((result.rows, result.valid_pdd_rows), (1, 0))
with result.output.open(encoding="utf-8-sig", newline="") as handle:
exported = next(csv.DictReader(handle))
self.assertEqual(exported["shopee_goods_id"], "24948397488")
self.assertEqual(exported["spec_raw"], "甲,乙")
self.assertEqual(exported["parse_ok"], "false")
self.assertEqual(exported["association_pdd_goods_id"], "")
self.assertEqual(exported["validation_code"], "PDD_URL_HOST_INVALID")
def test_输出目录不能位于输入目录内(self):
root, _, _ = self.make_source([])
args = catalog.build_parser().parse_args([str(root), "--output-dir", str(root / "csv")])
with self.assertRaisesRegex(catalog.CatalogExportError, "输出目录"):
catalog.run(args)
if __name__ == "__main__":
unittest.main()