generate_fixtures.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/env python3
  2. """生成 AI 数据清洗 E2E 验收用的 xlsx/csv 样本。
  3. 依赖:openpyxl
  4. 用法:python generate_fixtures.py # 输出到同目录 fixtures/
  5. """
  6. from __future__ import annotations
  7. import csv
  8. import os
  9. from openpyxl import Workbook
  10. from openpyxl.styles import Font
  11. OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures")
  12. os.makedirs(OUT, exist_ok=True)
  13. HEADERS = ["姓名", "身份证号", "手机号", "银行卡号", "交易日期", "交易时间", "金额", "数量", "备注"]
  14. ROWS = [
  15. ["张三", "11010519491231002X", "13800000000", "6222020200001234",
  16. "2026-01-05", "2026-01-05 10:30:00", "1,234.50", "3", "正常"],
  17. ["李四", "110105491231002", "+86 139-0000-1111", "6222 0202 0000 1235",
  18. "2026/1/6", "2026-01-06T11:00:00", "-100.00", "2", "负数金额"],
  19. ["王五", "12345", "123", "6.22202E+15",
  20. "2026年1月7日", "10:30", "(200.50)", "1.5", "坏证件/电话/卡/纯时间"],
  21. ["赵六", "110105194912310021", "13800002222", "6222020200001236",
  22. "2026-02-30", "25:00", "约100元", "abc", "坏日期/时间/金额/数量"],
  23. ["钱七", "11010519491231002X", "13800003333", "6222020200001237",
  24. "45000", "1704067200", "¥2,300.5", "10", "序列号/epoch"],
  25. ["孙八", "11010519491231002X", "13800004444", "6222020200001238",
  26. "20260108", "2026-01-08 09:00:00", "100元", "8", "紧凑日期/带元"],
  27. [],
  28. ["周九", "11010519491231002X", "13800005555", "6222020200001239",
  29. "2026-01-09", "2026-01-09 12:00:00", "300.00", "5", "空行后的行"],
  30. ]
  31. def save_xlsx(name: str, sheet_name: str, rows, headers=None, title=None, start_row=1,
  32. positions=None):
  33. wb = Workbook()
  34. ws = wb.active
  35. ws.title = sheet_name
  36. row = start_row
  37. if title:
  38. ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(headers or HEADERS))
  39. ws.cell(row=1, column=1, value=title).font = Font(bold=True)
  40. row = 3
  41. for c, h in enumerate(headers or HEADERS, 1):
  42. ws.cell(row=row, column=c, value=h).font = Font(bold=True)
  43. for i, values in enumerate(rows):
  44. target = positions[i] if positions else row + 1 + i
  45. for c, v in enumerate(values, 1):
  46. ws.cell(row=target, column=c, value=v)
  47. wb.save(os.path.join(OUT, name))
  48. def save_csv(name: str, rows):
  49. with open(os.path.join(OUT, name), "w", newline="", encoding="utf-8") as f:
  50. w = csv.writer(f)
  51. w.writerow(HEADERS)
  52. for values in rows:
  53. w.writerow(values if values else [""] * len(HEADERS))
  54. def main():
  55. # 01:自建表类型推断(标题行 + 空行 + 表头 + 空行隔断)
  56. save_xlsx("01_self_built_types.xlsx", "经营者信息", ROWS, title="经营者信息表")
  57. # 02:与 01 同表头但倒序(验证复用必须同序)
  58. save_xlsx("02_reordered_headers.xlsx", "乱序经营者",
  59. [list(reversed(r)) for r in ROWS[:3]], headers=list(reversed(HEADERS)))
  60. # 03:两列标题 + 空行 + 表头 + 空行隔断,验证表头定位与 row_no 缺口
  61. save_xlsx("03_messy_title_blank.xlsx", "人员交易", [
  62. ["张三", "1,000.00", "2026-01-01"],
  63. ["李四", "2,000.00", "2026-01-02"],
  64. ["王五", "3,000.00", "2026-01-03"],
  65. ["赵六", "坏金额", "坏日期"],
  66. ], headers=["姓名", "金额", "日期"], title="2026年人员交易明细",
  67. positions=[4, 5, 7, 8])
  68. # 04:CSV 版脏数据(验证 CSV 不再 Skip;可选列脏值只置空)
  69. save_csv("04_csv_types.csv", ROWS)
  70. # 05:同表头 20 行,1 行身份证非法(配合把 ai_clean_field.required 临时置 1,
  71. # 验证必填列坏值整行拒绝 + 失败明细)
  72. rows05 = []
  73. for i in range(1, 21):
  74. bad = i == 1
  75. rows05.append([
  76. "坏证件行" if bad else f"正常{i}",
  77. "12345" if bad else "11010519491231002X",
  78. "13800000000", "6222020200001234", "2026-01-05",
  79. "2026-01-05 10:30:00", "100.00", "1", "ok",
  80. ])
  81. save_xlsx("05_required_bad.xlsx", "经营者信息", rows05)
  82. # 07:同 05,但坏证件是完整 18 位(校验位错),验证失败明细不脱敏、原值完整展示
  83. rows07 = []
  84. for i in range(1, 21):
  85. bad = i == 1
  86. rows07.append([
  87. "坏18位证件行" if bad else f"正常{i}",
  88. "110105194912310021" if bad else "11010519491231002X",
  89. "13800000000", "6222020200001234", "2026-01-05",
  90. "2026-01-05 10:30:00", "100.00", "1", "ok",
  91. ])
  92. save_xlsx("07_required_bad_id18.xlsx", "经营者信息", rows07)
  93. # 06:干净 CSV(验证 CSV 正常入库)
  94. save_csv("06_csv_clean.csv", [
  95. [f"CSV正常{i}", "11010519491231002X", "13800000000", "6222020200001234",
  96. "2026-01-05", "2026-01-05 10:30:00", "100.00", "1", "ok"]
  97. for i in range(1, 8)
  98. ])
  99. print("fixtures written to", OUT)
  100. if __name__ == "__main__":
  101. main()