template7.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # coding:utf8
  2. import re
  3. from typing import Dict, Any
  4. from BiddingKG.dl.template_extract.abstract_template import AbstractTemplate
  5. import os
  6. import json
  7. class AdjustedProductInfoTemplate(AbstractTemplate):
  8. """
  9. 调整后的产品信息提取模板(适配data.json中的第二个表格结构)
  10. 从第二个表格提取产品相关信息
  11. """
  12. def __init__(self):
  13. super().__init__(
  14. template_id=os.path.abspath(__file__),
  15. priority=3
  16. )
  17. self.target_table = None # 第二个表格,存储产品信息
  18. def check_call_timing(self, preprocessed_data: Dict[str, Any]) -> bool:
  19. """检查是否符合模板调用条件"""
  20. if "表格列表" not in preprocessed_data:
  21. return False
  22. tables = preprocessed_data["表格列表"]
  23. if len(tables) < 1:
  24. print("表格数量不足,至少需要2个表格")
  25. return False
  26. try:
  27. self.target_table = tables[0] # 只处理第二个表格
  28. # 验证表格关键表头(根据data.json第二个表格实际结构泛化匹配)
  29. header_patterns = [
  30. (0, 0, r'采购品目|品目'), # 第1行第1列
  31. (0, 2, r'名称|产品名称'), # 第1行第3列
  32. (1, 0, r'单位|计量单位'), # 第2行第1列
  33. (1, 2, r'数量'), # 第2行第3列
  34. (3, 0, r'单价'), # 第4行第1列
  35. (3, 2, r'总价|总金额'), # 第4行第3列
  36. ]
  37. # 验证表头
  38. for row, col, pattern in header_patterns:
  39. if row >= len(self.target_table) or col >= len(self.target_table[row]):
  40. return False
  41. header_text = self.target_table[row][col].strip()
  42. if not re.search(pattern, header_text, re.IGNORECASE):
  43. print(f"表头不匹配: {header_text} 不符合 {pattern}")
  44. return False
  45. return True
  46. except Exception as e:
  47. print(f"表格验证错误: {e}")
  48. return False
  49. def extract(self, preprocessed_data: Dict[str, Any]) -> Dict[str, Any]:
  50. """提取表格中的产品信息"""
  51. result = {"产品信息": []}
  52. # 提取产品信息
  53. product_info = self._extract_product_info()
  54. if product_info:
  55. # 验证产品信息是否包含产品及其他至少两个要素
  56. if "产品" in product_info and len(product_info) >= 3:
  57. result["产品信息"].append(product_info)
  58. else:
  59. print("产品信息要素不足,不满足返回条件")
  60. return result
  61. def _get_value(self, table: list, row: int, col: int) -> str:
  62. """获取表格指定位置的值"""
  63. if row < len(table) and col < len(table[row]):
  64. return table[row][col].strip()
  65. return ""
  66. def _format_amount(self, value: str, header_row: int, header_col: int) -> str:
  67. """格式化金额,补充单位"""
  68. if not value:
  69. return ""
  70. # 检查值中是否已包含单位
  71. if re.search(r'[万亿美欧日]?元|¥|人民币', value):
  72. return value
  73. # 从表头获取单位补充
  74. header_text = self._get_value(self.target_table, header_row, header_col)
  75. if re.search(r'[万亿美欧日]?元|¥|人民币', header_text):
  76. unit = re.search(r'[万亿美欧日]?元|¥|人民币', header_text).group(0)
  77. return f"{value}{unit}"
  78. return value
  79. def _extract_product_info(self) -> Dict[str, Any]:
  80. """提取产品详细信息"""
  81. product = {
  82. "产品": self._get_value(self.target_table, 0, 3), # 产品名称
  83. "品目": self._get_value(self.target_table, 0, 1), # 采购品目
  84. "数量": self._get_value(self.target_table, 1, 3), # 数量
  85. "单位": self._get_value(self.target_table, 1, 1), # 计量单位
  86. "单价": self._format_amount(self._get_value(self.target_table, 3, 1), 3, 0), # 单价(补充单位)
  87. "总价": self._format_amount(self._get_value(self.target_table, 3, 3), 3, 2), # 总价(补充单位)
  88. # # 原表格中无品牌和规格信息,保留字段但值为空
  89. # "品牌": self._get_value(self.target_table, -1, -1), # 无效位置,确保为空
  90. # "规格": self._get_value(self.target_table, -1, -1) # 无效位置,确保为空
  91. }
  92. # 过滤空值字段
  93. filtered_product = {k: v for k, v in product.items() if v}
  94. return filtered_product
  95. # 使用示例
  96. if __name__ == "__main__":
  97. with open("data.json", "r", encoding="utf8") as f:
  98. preprocessed_data = json.load(f)
  99. template = AdjustedProductInfoTemplate()
  100. if template.check_call_timing(preprocessed_data):
  101. result = template.extract(preprocessed_data)
  102. print("提取结果:", json.dumps(result, ensure_ascii=False, indent=2))
  103. else:
  104. print("当前数据不满足模板调用条件")