| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- # coding:utf8
- import re
- from typing import Dict, Any
- from BiddingKG.dl.template_extract.abstract_template import AbstractTemplate
- import os
- import json
- class AdjustedProductInfoTemplate(AbstractTemplate):
- """
- 调整后的产品信息提取模板(适配data.json中的第二个表格结构)
- 从第二个表格提取产品相关信息
- """
- def __init__(self):
- super().__init__(
- template_id=os.path.abspath(__file__),
- priority=3
- )
- self.target_table = None # 第二个表格,存储产品信息
- def check_call_timing(self, preprocessed_data: Dict[str, Any]) -> bool:
- """检查是否符合模板调用条件"""
- if "表格列表" not in preprocessed_data:
- return False
- tables = preprocessed_data["表格列表"]
- if len(tables) < 1:
- print("表格数量不足,至少需要2个表格")
- return False
- try:
- self.target_table = tables[0] # 只处理第二个表格
- # 验证表格关键表头(根据data.json第二个表格实际结构泛化匹配)
- header_patterns = [
- (0, 0, r'采购品目|品目'), # 第1行第1列
- (0, 2, r'名称|产品名称'), # 第1行第3列
- (1, 0, r'单位|计量单位'), # 第2行第1列
- (1, 2, r'数量'), # 第2行第3列
- (3, 0, r'单价'), # 第4行第1列
- (3, 2, r'总价|总金额'), # 第4行第3列
- ]
- # 验证表头
- for row, col, pattern in header_patterns:
- if row >= len(self.target_table) or col >= len(self.target_table[row]):
- return False
- header_text = self.target_table[row][col].strip()
- if not re.search(pattern, header_text, re.IGNORECASE):
- print(f"表头不匹配: {header_text} 不符合 {pattern}")
- return False
- return True
- except Exception as e:
- print(f"表格验证错误: {e}")
- return False
- def extract(self, preprocessed_data: Dict[str, Any]) -> Dict[str, Any]:
- """提取表格中的产品信息"""
- result = {"产品信息": []}
- # 提取产品信息
- product_info = self._extract_product_info()
- if product_info:
- # 验证产品信息是否包含产品及其他至少两个要素
- if "产品" in product_info and len(product_info) >= 3:
- result["产品信息"].append(product_info)
- else:
- print("产品信息要素不足,不满足返回条件")
- return result
- def _get_value(self, table: list, row: int, col: int) -> str:
- """获取表格指定位置的值"""
- if row < len(table) and col < len(table[row]):
- return table[row][col].strip()
- return ""
- def _format_amount(self, value: str, header_row: int, header_col: int) -> str:
- """格式化金额,补充单位"""
- if not value:
- return ""
- # 检查值中是否已包含单位
- if re.search(r'[万亿美欧日]?元|¥|人民币', value):
- return value
- # 从表头获取单位补充
- header_text = self._get_value(self.target_table, header_row, header_col)
- if re.search(r'[万亿美欧日]?元|¥|人民币', header_text):
- unit = re.search(r'[万亿美欧日]?元|¥|人民币', header_text).group(0)
- return f"{value}{unit}"
- return value
- def _extract_product_info(self) -> Dict[str, Any]:
- """提取产品详细信息"""
- product = {
- "产品": self._get_value(self.target_table, 0, 3), # 产品名称
- "品目": self._get_value(self.target_table, 0, 1), # 采购品目
- "数量": self._get_value(self.target_table, 1, 3), # 数量
- "单位": self._get_value(self.target_table, 1, 1), # 计量单位
- "单价": self._format_amount(self._get_value(self.target_table, 3, 1), 3, 0), # 单价(补充单位)
- "总价": self._format_amount(self._get_value(self.target_table, 3, 3), 3, 2), # 总价(补充单位)
- # # 原表格中无品牌和规格信息,保留字段但值为空
- # "品牌": self._get_value(self.target_table, -1, -1), # 无效位置,确保为空
- # "规格": self._get_value(self.target_table, -1, -1) # 无效位置,确保为空
- }
- # 过滤空值字段
- filtered_product = {k: v for k, v in product.items() if v}
- return filtered_product
- # 使用示例
- if __name__ == "__main__":
- with open("data.json", "r", encoding="utf8") as f:
- preprocessed_data = json.load(f)
- template = AdjustedProductInfoTemplate()
- if template.check_call_timing(preprocessed_data):
- result = template.extract(preprocessed_data)
- print("提取结果:", json.dumps(result, ensure_ascii=False, indent=2))
- else:
- print("当前数据不满足模板调用条件")
|