diff --git a/flask_app/general/format_amout.py b/flask_app/general/format_amout.py new file mode 100644 index 0000000..d7a5b55 --- /dev/null +++ b/flask_app/general/format_amout.py @@ -0,0 +1,87 @@ +import re + +""" +处理全角点号->半角点号 +处理逗号分隔的数字: 你的当前代码无法处理包含逗号的数字,例如 "1,000元"。可以在提取数字之前移除逗号。 +优先级处理: 当前代码优先匹配“万元”然后是“元”。根据需求,可能需要调整优先级或提取所有匹配。 +处理缩写: 如果输入可能使用“万”而不是“万元”,需要添加相应的匹配模式。 +处理没有匹配的情况: 当没有匹配到金额时,返回一个默认值或提示信息。 +""" +import re + +def format_amount(original_amount): + """ + 格式化金额字符串 + + 参数: + original_amount (str): 输入的文本字符串 + + 返回: + str: 格式化后的金额字符串或提示信息 + """ + # 1. 删除所有空格和逗号 + amount_str = re.sub(r'[,,\s]', '', original_amount) + amount_str = amount_str.replace('.', '.') # 将全角点号转换为半角点号 + + # 2. 定义正则表达式模式,优先级依次为“元”、“万”/“万元”、无单位 + patterns = [ + (r"(\d+\.?\d*)元", 1), # 匹配“元”,乘以1 + (r"(\d+\.?\d*)万元?", 10000), # 匹配“万”或“万元”,乘以10,000 + (r"(\d+\.?\d*)(?![万|元])", 1) # 匹配没有“万”或“元”的数值,默认乘以1 + ] + + # 3. 遍历模式并尝试匹配 + for pattern, multiplier in patterns: + match = re.search(pattern, amount_str) + if match: + try: + value = float(match.group(1)) + value *= multiplier + # 格式化为整数,四舍五入 + formatted_amount = "{:.0f}".format(value) + return formatted_amount + except ValueError: + continue # 如果转换失败,尝试下一个模式 + + # 4. 如果没有匹配到任何模式,返回默认提示信息 + return "" + +if __name__ == "__main__": +# 测试用例 + + input_tests = [ + "RMB100.01万元威威", + "预算为200.6元", + "总金额为3.5万元", + "费用为1,000元", + "预计支出为50,000元", + "项目预算未确定", + "金额为-1,500元", + "总计为2万元和3,000元", + "合计为5万人民币", + "资金需求量为0.75万", + "支出预计为100元和200元", + "11000 万元", + "预算为100万元", + "费用为100元人民币", + "金额:¥300.50元", + "支出为30,000元及50万", + "费用预计为", + "成本为0元", + "支出为1.5万", + "总金额为100.5元", + "RMB1,234.56万元项目", + "项目费用为¥7,890元", + "预计投资-2.5万元", + "支出为万100元", # 非标准格式,应返回默认提示 + "伍万元整(50,000.00 元)", + "金额为人民币3万5千元", # 包含中文数字组合 + "金额10,000 (壹万元)" + ] + + for test in input_tests: + formatted = format_amount(test) + print(f"输入: '{test}' -> 输出: '{formatted}'") + + + diff --git a/flask_app/general/post_processing.py b/flask_app/general/post_processing.py index 0af460f..6f8c632 100644 --- a/flask_app/general/post_processing.py +++ b/flask_app/general/post_processing.py @@ -2,7 +2,8 @@ import json import re from flask_app.general.format_date import format_chinese_date - +from flask_app.general.format_amout import format_amount +from flask_app.general.纯技术参数要求提取 import extract_matching_keys # 定义一个辅助函数用于获取嵌套字典中的值 def get_nested(dic, keys, default=None): for key in keys: @@ -148,7 +149,12 @@ def inner_post_processing(base_info): formatted_value = format_chinese_date(value) # 或者使用 format_chinese_date(value) 如果你定义了该函数 extracted_info[new_key] = ensure_string(formatted_value) if formatted_value else "" else: - extracted_info[new_key] = ensure_string(value) if value else "" + # 对 '招标项目预算' 应用 format_amount + if new_key == "招标项目预算" and value: + formatted_amount = format_amount(ensure_string(value)) + extracted_info[new_key] = formatted_amount + else: + extracted_info[new_key] = ensure_string(value) if value else "" # 特殊处理 '招标项目地点' # 在 '项目信息' 下查找包含 "地点" 的键 @@ -201,12 +207,17 @@ def inner_post_processing(base_info): if not isinstance(guarantee_info, dict): guarantee_info = {} bid_bond = extract_bid_bond(guarantee_info) - extracted_info["投标保证金"] = ensure_string(bid_bond) if bid_bond else "" + # 对 '投标保证金' 应用 format_amount + if bid_bond: + formatted_bid_bond = format_amount(ensure_string(bid_bond)) + extracted_info["投标保证金"] = formatted_bid_bond + else: + extracted_info["投标保证金"] = "" return extracted_info def outer_post_processing(combined_data, includes,good_list): - print(good_list) + # print(good_list) """ 外层处理函数,调用内层 post_processing 处理 '基础信息',并构建 processed_data。 额外提取 '采购要求' 下的 '技术要求' 内容。 @@ -234,12 +245,13 @@ def outer_post_processing(combined_data, includes,good_list): extracted_info = inner_post_processing(base_info) # 将 '基础信息' 保留在处理后的数据中 processed_data["基础信息"] = base_info - # 提取 '采购要求' 下的 '技术要求' - procurement_reqs = get_nested(base_info, ["采购要求", "技术要求"], "") - if not procurement_reqs: + tech_requirements = get_nested(base_info, ["采购要求", "技术要求"], {}) + if tech_requirements: + procurement_reqs = extract_matching_keys(tech_requirements,good_list) + else: # 如果 '技术要求' 不存在或为空,可以根据需要设置默认值 - procurement_reqs = "未提供" # 或者其他适当的默认值 + procurement_reqs = "未提供" # 遍历原始字典的每一个键值对 for key, value in combined_data.items(): @@ -307,394 +319,44 @@ if __name__ == "__main__": "是否接受联合体投标": "否" }, "采购要求": { - "技术要求": { - "交通信号灯": { - "单灯技术要求": "1、道路交通信号灯单灯必须符合国家标准GB14887-2011《道路交通信号灯》全部技术规定,并通过公安部交通安全产品质量监督检测中心的检测。", - "光源要求": "2、道路交通信号灯光源必须采用户外型超亮度发光二极管(LED),使用寿命不少于50000小时。", - "材质要求": "3、信号灯灯具材质为铝质金属材料。机动车信号灯灯芯透镜尺寸采用¢400mm规格,人行信号灯灯芯透镜尺寸采用¢300mm,相同规格的灯芯可以互换。信号灯外观应与目前广水市使用的信号灯外观相一致。", - "供电电路要求": "4、信号灯需采用恒流供电电路,单体信号灯功率¢400mm规格不超过20VA;¢300mm规格不超过 15VA。", - "倒计时器要求": "1、道路交通信号倒计时器安装在信号灯的上方或右方,2位数码显示倒九秒提示。当机动车信号灯采用悬臂式杆件时,机动车信号灯倒计时器规格为 800×600,当采用立柱式杆件时,倒计时器规格为 400×400。人行信号灯倒计时显示器透光面为Φ300mm或 300mm ×300mm。倒计时显示器的光学性能、工作条件、机械强度、电气性能均符合国家安全行业标准GA/T508-2004《道路交通信号倒计时显示器》的全部技术规定。", - "倒计时器运行要求": "2、倒计时器运行中遇到电磁、静电、电网等干扰时不能有死机现象。", - "倒计时器测试要求": "3、倒计时器必须经过过电压、过电流测试,具有防雷击功能。", - "倒计时器触发方式": "4、倒计时器应为学习型,并支持脉冲触发、黄灯触发及通讯式触发。", - "信号灯杆技术要求": "1、信号灯杆所属的立柱、法兰盘、地脚螺栓、螺母、垫片、加强筋等金属构件及悬臂、支撑臂、拉杆、抱箍座、夹板等附件的防腐性能应符合GB/T18226《公路交通工程钢构件防腐技术条件》的规定。", - "信号灯杆材质要求": "2、信号灯杆应采用圆形或多棱形经热镀锌处理的钢管制造;悬臂式灯杆悬臂杆与支撑杆使用圆形或多棱形的变截面型材制作,悬臂与灯杆连接端宜焊接固定法兰盘,悬臂下应留有进出线孔。", - "信号灯杆表面处理": "3、信号灯杆制作后须经过防锈处理,底层喷涂富锌防锈底漆,外层喷涂银灰色瓷漆。", - "信号灯杆底部要求": "4、信号灯灯杆距路面约 300-350mm处留有拉线孔和拉线孔门。孔门盖应设有防盗措施,孔内设置接地端子座,并与接地线可靠接驳。", - "信号灯杆顶部要求": "5、立柱式灯杆顶部安装灯具处应留有出线孔,并配备橡胶护套、电缆线回水弯挂钩,灯杆顶部应安装塑料或经防腐处理的内套式金属防水管帽。", - "悬臂式灯杆拉杆要求": "6、悬臂式灯杆拉杆宜使用圆钢制作,一端配有可调距离的螺旋扣,直径和长度根据悬臂长度确定。", - "信号灯杆法兰盘要求": "7、信号灯杆杆体底部应焊接固定法兰盘,法兰盘与杆体之间应均匀焊接加强筋。", - "人行信号灯设计要求": "8、一体式人行信号灯采用整灯嵌入式设计、结构紧凑、方便拆装、便于维护。杆体前后金属面板喷塑处理,两侧铝型材包边。" - }, - "交通监控视频子系统": { - "高清视频抓拍像机": { - "有效像素": "≥900W像素", - "最低照度": "彩色≤0.001lx", - "传感器类型": "≥1英寸全局曝光COMS/GMOS/GS COMS", - "电子快门": "至少满足 1/25s至 1/100,000s,可调", - "视频压缩标准": "至少支持H264、H265等", - "视频分辨率": "≥4096×2160,向下可设置", - "视频流帧率": "≥25fps,至少双视频流", - "图片压缩方式": "JPEG", - "图像分辨率": "≥4096(H)×2160(V)", - "强光抑制": "具备", - "API接口开放": "具备;支持标准ONVIF协议与第三方厂家设备进行互联;支持GB/T28181;应提供 SDK", - "通讯接口": "≥1个 RJ45,10M/100M/1000M自适应以太网电口;≥1个 RS-485接口", - "前端存储卡": "嵌入式,支持断网时本地存储,裸容量≥128GB", - "具备其他功能": "应具备I/O触发、RS-485触发、视频触发,支持电源同步;支持频闪式卜光装置和脉冲式补光装置同步补光", - "具备其他功能2": "具备AI深度学习算法和GPU芯片", - "光圈、聚焦": "手动光圈;焦距应可根据车道宽度及抓拍距离进行调整设置,要求中心成像圆内解像力不小于 900万像素,边缘解像力不低于中心 60%,镜头的成像尺寸应与摄像机成像靶面尺寸相等或略大。镜头应配置电动偏振镜,具备根据环境自动切换功能", - "防护罩类型": "室外型防护罩,含底座;具备隔热防潮、防水、防尘、防腐、防震等功能;具有加热器、支架、遮阳罩等,具有良好的密封性和恒温等功能。", - "防护等级": "≥IP66" - }, - "补光灯": { - "配置方式": "每个车道配置≥1台;补光装置必须与高清摄像设备高度匹配", - "LED管芯": "采用超高亮大功率白光LED管芯,灯珠数量不少于 20颗", - "功耗": "30W/车道≤单台平均功耗≤50W/车道,可调", - "峰值光照度(基准轴)": "≤300lx", - "峰值光照度(补光区)": "应大于等于基准轴上有效光照度的 50%", - "平均光照度": "≤50lx", - "闪光频率": "≥50Hz;补光装置应能与集成式高清摄像设备同步", - "有效补光距离": "≥25m", - "最大点亮时间": "≤4ms(可调节)", - "控制方式": "电平,同步触发方式", - "安全性": "在保证瞬时亮度的前提下,必须进行防炫目处理,不会造成光污染", - "使用寿命": "≥50000小时", - "防护等级": "不低于IP65", - "其它": "应配置光栅装置或遮光阻断装置" - }, - "闪光灯": { - "色温范围": "5500±500K", - "补光距离": "16m~30m", - "回电时间": "≤60ms,满足相机 2张连拍需求", - "闪光灯寿命": ">500万次", - "自带光敏控制": "可根据环境亮度自动调节闪光强度", - "防护等级": "IP66", - "工作温度范围": "在-20℃~70℃温度范围内均能正常工作" - }, - "光纤收发器": { - "1路千兆以太网": "1路千兆以太网。", - "单模单纤": "单模单纤,光接口为FC接口,满足实际传输距离要求。", - "10/100/1000M自适应以太网接口": "10/100/1000M自适应以太网接口。", - "工作环境适应性强": "工作环境适应性强,满足全天候使用的要求。", - "耐压": "耐压≥300V。" - }, - "交换机": { - "交换容量": "≥6Gbps,包转发率≥7Mpps;MAC地址列表≥8K;应具备线性转发能力;", - "以太网接口": "应至少具有 8个 10/100/1000M自适应以太网接口和至少 2个 1000M光口;", - "以太网光端口传输距离": "应不小于 40km,以太网光模块为单芯双向光模块,光口接口类型为LC型接口,光模块连接单模光纤;", - "支持协议": "至少支持 IEEE802.1p、IEEE802.1q、IEEE802.3、IEEE802.3u、IEEE802.3z、IEEE802.3x等协议;", - "VLAN功能": "应具有 IEEE802.1Q VLAN,应实现信号控制独立传输,至少支持 4个 VLAN划分;", - "路由协议": "应至少支持三层动态路由协议;", - "QOS功能": "应具有 IEEE802.1p_QOS功能;", - "组播功能": "应具有 IGMP静态组播、端口聚合、端口镜像等功能;", - "防护等级": "IP40以上等级防护;", - "设计要求": "应采用无风扇设计;", - "网管功能": "应具有网管功能。" - }, - "终端服务器": { - "结构形式": "采用嵌入式架构;", - "操作系统": "嵌入式操作系统;", - "接入路数": "提供≥12路高清摄像机视频存储、过车记录存储、图片存储、数据上传、视频流转发等;", - "主机存储": "内置 SATA接口;配置存储容量≥16T硬盘 ;", - "网络接口": "提供≥8个 RJ45 1000M网络接口;", - "其他接口": "提供 RS232、RS485、外置 USB接口、VGA接口等;", - "访问操作": "支持 Web操作访问;", - "接口协议": "至少支持 ONVIF,GB/T28181等;", - "API接口开放支持": "支持标准ONVIF协议与第三方厂家设备进行互通;支持 GB/T 28181。", - "支持套牌车检测": "可将抓拍图片与本地历史数据进行车辆特征比对分析,检测出套牌车辆,同时给出告警提示" - } - }, - "交通诱导子系统": { - "交通诱导屏": { - "主要特性": "1)温度范围-40~70℃ 2)光带宽度>130mm 3)通迅接口:RS485、网络通讯、3G网络 4)视角:水平:110°~120°垂直:55° 5)发光亮度:6500-7000 cd/m2 6)平整度≤0.5mm 7)使用寿命≥10万小时 8)平均故障时间≥1万小时 9)电源采用 n+1高可靠容错的开关电源系统 10)显示尺寸:长 3.84米×高 2.56米=9.83平方米 11)机箱要求:冷轧钢板,机箱为内外两层,内箱体为全封闭、全天候、防风雨型,符合IP65防护等级 12)抗风等级:40m/s", - "技术参数": "1)物理点间距:10mm2)物理密度:10000点/m23)发光点颜色:1R1G 4)基色:纯红+纯绿 5)模组尺寸:320mm*160mm 6)刷新频率:≥800HZ 7)工作电压:AC220V±10%,50Hz(三相五线制)8)平均功耗:350W/m2 9)最大功耗:≤700W/ m2" - } - }, - "电子警察子系统": { - "高清视频抓拍像机": { - "摄像机.有效像素": "≥900W像素", - "摄像机.最低照度": "彩色≤0.001lx", - "摄像机.传感器类型": "≥1英寸全局曝光COMS/GMOS/GS COMS", - "摄像机.电子快门": "至少满足 1/25s至 1/100,000s,可调", - "视频图像.视频压缩标准": "至少支持H264、H265等", - "视频图像.视频分辨率": "≥4096×2160,向下可设置", - "视频图像.视频流帧率": "≥25fps,至少双视频流", - "视频图像.图片压缩方式": "JPEG", - "视频图像.图像分辨率": "≥4096(H)×2160(V)", - "视频图像.强光抑制": "具备", - "协议.API接口开放": "具备;支持标准ONVIF协议与第三方厂家设备进行互联;支持GB/T28181;应提供 SDK", - "接口.通讯接口": "≥1个 RJ45,10M/100M/1000M自适应以太网电口;≥1 个 RS-485接口", - "接口.前端存储卡": "嵌入式,支持断网时本地存储,裸容量≥128GB", - "功能.具备其他功能": "应具备I/O触发、RS-485触发、视频触发,支持电源同步;支持频闪式卜光装置和脉冲式补光装置同步补光", - "功能.具备其他功能.1": "具备AI深度学习算法和GPU芯片", - "高清工业级镜头.光圈、聚焦": "手动光圈;焦距应可根据车道宽度及抓拍距离进行调整设置,要求中心成像圆内解像力不小于 900万像素,边缘解像力不低于中心 60%,镜头的成像尺寸应与摄像机成像靶面尺寸相等或略大。镜头应配置电动偏振镜,具备根据环境自动切换功能", - "防护罩.防护罩类型": "室外型防护罩,含底座;具备隔热防潮、防水、防尘、防腐、防震等功能;具有加热器、支架、遮阳罩等,具有良好的密封性和恒温等功能。", - "防护罩.防护等级": "≥IP66" - }, - "补光灯": { - "配置方式": "每个车道配置≥1台;补光装置必须与高清摄像设备高度匹配", - "LED管芯": "采用超高亮大功率白光LED管芯,灯珠数量不少于 20颗", - "功耗": "30W/车道≤单台平均功耗≤50W/车道,可调", - "峰值光照度(基准轴)": "≤300lx", - "峰值光照度(补光区)": "应大于等于基准轴上有效光照度的 50%", - "平均光照度": "≤50lx", - "闪光频率": "≥50Hz;补光装置应能与集成式高清摄像设备同步", - "有效补光距离": "≥25m", - "最大点亮时间": "≤4ms(可调节)", - "控制方式": "电平,同步触发方式", - "安全性": "在保证瞬时亮度的前提下,必须进行防炫目处理,不会造成光污染", - "使用寿命": "≥50000小时", - "防护等级": "不低于IP65", - "其它": "应配置光栅装置或遮光阻断装置" - }, - "闪光灯": { - "色温范围": "5500±500K", - "补光距离": "16m~30m", - "回电时间": "≤60ms,满足相机 2张连拍需求", - "闪光灯寿命": ">500万次", - "自带光敏控制": "可根据环境亮度自动调节闪光强度", - "防护等级": "IP66", - "工作温度范围": "在-20℃~70℃温度范围内均能正常工作" - }, - "光纤收发器": { - "1路千兆以太网": "1路千兆以太网。", - "单模单纤": "单模单纤,光接口为FC接口,满足实际传输距离要求。", - "10/100/1000M自适应以太网接口": "10/100/1000M自适应以太网接口。", - "工作环境适应性强": "工作环境适应性强,满足全天候使用的要求。", - "耐压": "耐压≥300V。" - }, - "交换机": { - "交换容量": "≥6Gbps,包转发率≥7Mpps;MAC地址列表≥8K;应具备线性转发能力;", - "以太网接口": "应至少具有 8个 10/100/1000M自适应以太网接口和至少 2个 1000M光口;", - "以太网光端口传输距离": "应不小于 40km,以太网光模块为单芯双向光模块,光口接口类型为LC型接口,光模块连接单模光纤;", - "支持协议": "至少支持 IEEE802.1p、IEEE802.1q、IEEE802.3、IEEE802.3u、IEEE802.3z、IEEE802.3x等协议;", - "VLAN功能": "应具有 IEEE802.1Q VLAN,应实现信号控制独立传输,至少支持 4个 VLAN划分;", - "动态路由协议": "应至少支持三层动态路由协议;", - "QOS功能": "应具有 IEEE802.1p_QOS功能;", - "组播功能": "应具有 IGMP静态组播、端口聚合、端口镜像等功能;", - "防护等级": "IP40以上等级防护;", - "设计要求": "应采用无风扇设计;", - "网管功能": "应具有网管功能。" - }, - "终端服务器": { - "结构形式": "采用嵌入式架构;", - "操作系统": "嵌入式操作系统;", - "接入路数": "提供≥12路高清摄像机视频存储、过车记录存储、图片存储、数据上传、视频流转发等;", - "主机存储": "内置 SATA接口;配置存储容量≥16T硬盘 ;", - "网络接口": "提供≥8个 RJ45 1000M网络接口;", - "其他接口": "提供 RS232、RS485、外置 USB接口、VGA接口等;", - "访问操作": "支持 Web操作访问;", - "接口协议": "至少支持 ONVIF,GB/T28181等;", - "API接口开放支持": "支持标准ONVIF协议与第三方厂家设备进行互通;支持 GB/T 28181。", - "支持套牌车检测": "可将抓拍图片与本地历史数据进行车辆特征比对分析,检测出套牌车辆,同时给出告警提示" - } - }, - "交通卡口子系统": { - "高清视频抓拍像机": { - "摄像机.有效像素": "≥900W像素", - "摄像机.最低照度": "彩色≤0.001lx", - "摄像机.传感器类型": "≥1英寸全局曝光COMS/GMOS/GS COMS", - "摄像机.电子快门": "至少满足 1/25s至 1/100,000s,可调", - "视频图像.视频压缩标准": "至少支持H264、H265等", - "视频图像.视频分辨率": "≥4096×2160,向下可设置", - "视频图像.视频流帧率": "≥25fps,至少双视频流", - "视频图像.图片压缩方式": "JPEG", - "视频图像.图像分辨率": "≥4096(H)×2160(V)", - "视频图像.强光抑制": "具备", - "协议.API接口开放": "具备;支持标准ONVIF协议与第三方厂家设备进行互联;支持GB/T28181;应提供 SDK", - "接口.通讯接口": "≥1个 RJ45,10M/100M/1000M自适应以太网电口;≥1 个 RS-485接口", - "接口.前端存储卡": "嵌入式,支持断网时本地存储,裸容量≥128GB", - "功能.具备其他功能": "应具备I/O触发、RS-485触发、视频触发,支持电源同步;支持频闪式卜光装置和脉冲式补光装置同步补光", - "功能.具备其他功能.2": "具备AI深度学习算法和GPU芯片", - "高清工业级镜头.光圈、聚焦": "手动光圈;焦距应可根据车道宽度及抓拍距离进行调整设置,要求中心成像圆内解像力不小于 900万像素,边缘解像力不低于中心 60%,镜头的成像尺寸应与摄像机成像靶面尺寸相等或略大。镜头应配置电动偏振镜,具备根据环境自动切换功能", - "防护罩.防护罩类型": "室外型防护罩,含底座;具备隔热防潮、防水、防尘、防腐、防震等功能;具有加热器、支架、遮阳罩等,具有良好的密封性和恒温等功能。", - "防护罩.防护等级": "≥IP66" - }, - "补光灯": { - "配置方式": "每个车道配置≥1台;补光装置必须与高清摄像设备高度匹配", - "LED管芯": "采用超高亮大功率白光LED管芯,灯珠数量不少于 20颗", - "功耗": "30W/车道≤单台平均功耗≤50W/车道,可调", - "峰值光照度(基准轴)": "≤300lx", - "峰值光照度(补光区)": "应大于等于基准轴上有效光照度的 50%", - "平均光照度": "≤50lx", - "闪光频率": "≥50Hz;补光装置应能与集成式高清摄像设备同步", - "有效补光距离": "≥25m", - "最大点亮时间": "≤4ms(可调节)", - "控制方式": "电平,同步触发方式", - "安全性": "在保证瞬时亮度的前提下,必须进行防炫目处理,不会造成光污染", - "使用寿命": "≥50000小时", - "防护等级": "不低于IP65", - "其它": "应配置光栅装置或遮光阻断装置" - }, - "闪光灯": { - "色温范围": "5500±500K", - "补光距离": "16m~30m", - "回电时间": "≤60ms,满足相机 2张连拍需求", - "闪光灯寿命": ">500万次", - "自带光敏控制": "可根据环境亮度自动调节闪光强度", - "防护等级": "IP66", - "工作温度范围": "在-20℃~70℃温度范围内均能正常工作" - }, - "光纤收发器": { - "1路千兆以太网": "1路千兆以太网。", - "单模单纤": "单模单纤,光接口为FC接口,满足实际传输距离要求。", - "10/100/1000M自适应以太网接口": "10/100/1000M自适应以太网接口。", - "工作环境适应性强": "工作环境适应性强,满足全天候使用的要求。", - "耐压": "耐压≥300V。" - }, - "交换机": { - "交换容量": "≥6Gbps,包转发率≥7Mpps;MAC地址列表≥8K;应具备线性转发能力;", - "以太网接口": "应至少具有 8个 10/100/1000M自适应以太网接口和至少 2个 1000M光口;", - "以太网光端口传输距离": "应不小于 40km,以太网光模块为单芯双向光模块,光口接口类型为LC型接口,光模块连接单模光纤;", - "支持协议": "至少支持 IEEE802.1p、IEEE802.1q、IEEE802.3、IEEE802.3u、IEEE802.3z、IEEE802.3x等协议;", - "VLAN功能": "应具有 IEEE802.1Q VLAN,应实现信号控制独立传输,至少支持 4个 VLAN划分;", - "路由协议": "应至少支持三层动态路由协议;", - "QOS功能": "应具有 IEEE802.1p_QOS功能;", - "组播功能": "应具有 IGMP静态组播、端口聚合、端口镜像等功能;", - "防护等级": "IP40以上等级防护;", - "设计要求": "应采用无风扇设计;", - "网管功能": "应具有网管功能。" - }, - "终端服务器": { - "结构形式": "采用嵌入式架构;", - "操作系统": "嵌入式操作系统;", - "接入路数": "提供≥12路高清摄像机视频存储、过车记录存储、图片存储、数据上传、视频流转发等;", - "主机存储": "内置 SATA接口;配置存储容量≥16T硬盘 ;", - "网络接口": "提供≥8个 RJ45 1000M网络接口;", - "其他接口": "提供 RS232、RS485、外置 USB接口、VGA接口等;", - "访问操作": "支持 Web操作访问;", - "接口协议": "至少支持 ONVIF,GB/T28181等;", - "API接口开放支持": "支持标准 ONVIF协议与第三方厂家设备进行互通;支持 GB/T 28181。", - "支持套牌车检测": "可将抓拍图片与本地历史数据进行车辆特征比对分析,检测出套牌车辆,同时给出告警提示" - } - }, - "区间测速子系统": { - "高清视频抓拍像机": { - "1.摄像机.有效像素": "≥900W像素", - "1.摄像机.最低照度": "彩色≤0.001lx", - "1.摄像机.传感器类型": "≥1英寸全局曝光COMS/GMOS/GS COMS", - "1.摄像机.电子快门": "至少满足 1/25s至 1/100,000s,可调", - "2.视频图像.视频压缩标准": "至少支持H264、H265等", - "2.视频图像.视频分辨率": "≥4096×2160,向下可设置", - "2.视频图像.视频流帧率": "≥25fps,至少双视频流", - "3.视频图像.图片压缩方式": "JPEG", - "3.视频图像.图像分辨率": "≥4096(H)×2160(V)", - "3.视频图像.强光抑制": "具备", - "4.协议.API接口开放": "具备;支持标准ONVIF协议与第三方厂家设备进行互联;支持GB/T28181;应提供 SDK", - "5.接口.通讯接口": "≥1个 RJ45,10M/100M/1000M自适应以太网电口;≥1 个 RS-485接口", - "5.接口.前端存储卡": "嵌入式,支持断网时本地存储,裸容量≥128GB", - "5.功能.具备其他功能": "具备AI深度学习算法和GPU芯片", - "6.高清工业级镜头.光圈、聚焦": "手动光圈;焦距应可根据车道宽度及抓拍距离进行调整设置,要求中心成像圆内解像力不小于 900万像素,边缘解像力不低于中心 60%,镜头的成像尺寸应与摄像机成像靶面尺寸相等或略大。镜头应配置电动偏振镜,具备根据环境自动切换功能", - "7.防护罩.防护罩类型": "室外型防护罩,含底座;具备隔热防潮、防水、防尘、防腐、防震等功能;具有加热器、支架、遮阳罩等,具有良好的密封性和恒温等功能。", - "7.防护罩.防护等级": "≥IP66" - }, - "补光灯": { - "配置方式": "每个车道配置≥1台;补光装置必须与高清摄像设备高度匹配", - "LED管芯": "采用超高亮大功率白光LED管芯,灯珠数量不少于 20颗", - "功耗": "30W/车道≤单台平均功耗≤50W/车道,可调", - "峰值光照度(基准轴)": "≤300lx", - "峰值光照度(补光区)": "应大于等于基准轴上有效光照度的 50%", - "平均光照度": "≤50lx", - "闪光频率": "≥50Hz;补光装置应能与集成式高清摄像设备同步", - "有效补光距离": "≥25m", - "最大点亮时间": "≤4ms(可调节)", - "控制方式": "电平,同步触发方式", - "安全性": "在保证瞬时亮度的前提下,必须进行防炫目处理,不会造成光污染", - "使用寿命": "≥50000小时", - "防护等级": "不低于IP65", - "其它": "应配置光栅装置或遮光阻断装置" - }, - "闪光灯": { - "色温范围": "5500±500K", - "补光距离": "16m~30m", - "回电时间": "≤60ms,满足相机 2张连拍需求", - "闪光灯寿命": ">500万次", - "自带光敏控制": "可根据环境亮度自动调节闪光强度", - "防护等级": "IP66", - "工作温度范围": "在-20℃~70℃温度范围内均能正常工作" - }, - "光纤收发器": { - "1路千兆以太网": "1路千兆以太网。", - "单模单纤": "单模单纤,光接口为FC接口,满足实际传输距离要求。", - "10/100/1000M自适应以太网接口": "10/100/1000M自适应以太网接口。", - "工作环境适应性强": "工作环境适应性强,满足全天候使用的要求。", - "耐压": "耐压≥300V。" - }, - "交换机": { - "交换容量": "≥6Gbps", - "包转发率": "≥7Mpps", - "MAC地址列表": "≥8K", - "线性转发能力": "应具备线性转发能力", - "以太网接口": "应至少具有 8个 10/100/1000M自适应以太网接口和至少 2个 1000M光口", - "以太网光端口传输距离": "应不小于 40km,以太网光模块为单芯双向光模块,光口接口类型为LC型接口,光模块连接单模光纤", - "支持协议": "至少支持 IEEE802.1p、IEEE802.1q、IEEE802.3、IEEE802.3u、IEEE802.3z、IEEE802.3x等协议", - "VLAN": "应具有 IEEE802.1Q VLAN,应实现信号控制独立传输,至少支持 4个 VLAN划分", - "三层动态路由协议": "应至少支持三层动态路由协议", - "QOS功能": "应具有 IEEE802.1p_QOS功能", - "IGMP静态组播": "应具有 IGMP静态组播、端口聚合、端口镜像等功能", - "防护等级": "IP40以上等级防护", - "无风扇设计": "应采用无风扇设计", - "网管功能": "应具有网管功能" - }, - "终端服务器": { - "结构形式": "采用嵌入式架构;", - "操作系统": "嵌入式操作系统;", - "接入路数": "提供≥8路高清摄像机视频存储、过车记录存储、图片存储、数据上传、视频流转发等;", - "主机存储": "内置 SATA接口;配置存储容量≥16T硬盘 ;", - "网络接口": "提供≥8个 RJ45 1000M网络接口;", - "其他接口": "提供 RS232、RS485、外置 USB接口、VGA接口等;", - "访问操作": "支持 Web操作访问;", - "接口协议": "至少支持 ONVIF,GB/T28181等;", - "API接口开放支持": "支持标准ONVIF协议与第三方厂家设备进行互通;支持 GB/T 28181。" - } - }, - "后台接入服务器": { - "1、机架式服务器": "机架式服务器;", - "2、处理器": "处理器:至少配置 2颗单颗 10核 CPU,单核 CPU主频≥2.0GHz;", - "3、内存": "内存:配置 128GB DDR4内存;", - "4、硬盘": "硬盘:配置 6块 1.2T SAS硬盘,转速≥10Krpm;", - "5、RAID": "RAID:配置 RAID控制器,支持 RAID0、1、10、1E、5、50、60等;", - "6、网络": "网络:配置双千兆网卡;", - "7、电源": "电源:双电源;" - }, - "存储服务器": { - "1": "4U 48盘位磁盘阵列;", - "2": "单设备配置 64位多核处理器;", - "3": "16GB缓存;", - "4": "冗余电源;", - "5": "支持 SATA硬盘;", - "6": "2个千兆网口;", - "7": "1个系统 SSD盘;", - "8": "支持视音频、图片、直接写入,支持视频高速预览、回放、下载,支持云内容灾备份,支持一体化运维,支持GB/T28181-2011、Onvif、RTSP、H265、SVAC等标准视频协议。" - }, - "硬盘": { - "容量": "4T", - "尺寸": "3.5寸", - "接口": "SATA" - }, - "室外挂箱": { - "安装方式": "采用悬挂式安装方式,悬挂于杆件立柱,高度应确保机箱下边缘距离地面净高 2.5 米以上。设备机箱安装后不得侵入机动车道建筑界限以内,不得影响车辆正常通行。设备机箱应安装牢固;", - "表面处理": "设备机箱表面应经过考漆处理,应具备防锈蚀、防盐雾、防霉菌能力;", - "内部空间": "机箱内部空间应足够大,能确保设备、装置的合理摆放,设有存放用户手册、说明书、接线图、维修记录等资料的存储盒,并有适当空间预留。机箱空间应有利于机箱内各设备单元的散热、安装、使用和维修,同时应提供设备辅助散热措施,提高系统环境适应能力;", - "防护等级": "设备机箱的结构应能防雨并能降低灰尘及有害物质的侵入,机箱门盖应有溢水槽,机箱门内侧应配备密封条,机箱顶部应具有防积水措施。机箱防护等级应达到IP55以上;", - "机械强度": "机箱结构应具有足够的机械强度,应能承受正常条件下可预料到的运输、安装、搬运、维护等过程中的操作;", - "门的设计": "机箱门的最大开启角度应大于 120°。机箱门锁应采用保险柜天地锁式的结构设计防止被非法打开,门锁至少可对上、下及左右侧中的一侧进行缩栓式保护,应具备较强的设备防砸、防盗能力。机箱应具有防盗报警功能,机箱在非正常状态下开启时能够报警提示。机箱门接缝处有耐久且有弹性的密封垫,密封垫连续设置,无间断接口。机柜门锁上后,无松动、变形现象;", - "电源保护": "机箱内设应置有具备稳压、过载、漏电、短路保护功能的电源开关和防雷保护功能的电源浪涌保护器。在熔断器和电源开关等处应有警告标志。机箱内合适位置配备接地铜排,接地铜排的截面应不小于 100 mm2,接地端子应进行防腐处理。并应设置接地标志;接地铜排应保证良好接地,接地线截面积应不小于 16mm2;", - "电源插座": "机箱内应配备不少于 2路单相 2孔扁圆电源插座、2路单相 3孔扁圆电源插座;", - "电源开关": "应具有稳压、短路、过载、漏电保护;电源保护响应时间应为纳秒级;开关的额定电压、额定电流值应满足设备正常运行的要求;机械寿命应不少于 20000次;具有良好的散热性能。", - "额外要求": "室外大机箱需满足上述使用外,还应可安装前端管理主机。" - }, - "交通管道": { - "过街管道": "主要垂直于道路中线埋设,可开挖路段采用 DN90镀锌钢管,不宜开挖路段根据现场情况采用拖拉管(DN90 PE管)。路口必须在各方向埋设双管。", - "非过街管道": "采用 PE双壁波纹管。", - "干线(纵向)路段": "两接线井之间最大距 50m。", - "管道埋设深度": "机动车道和非机动车道下管道埋设深度(管顶至路面)应≥0.7m,人行道及绿化带下管道埋设深度(管顶至路面)应≥0.5m。如不能达到上述埋设深度要求应采取混凝土包封或采用钢管等保护措施。", - "管道敷设的坡度": "应为 0.3%-0.4%,不得小于 0.25%。", - "其他敷设要求": "应参照《市政公用工程细部构造做法(湖北省)》中《交通管道预埋断面图》做法。", - "交通管道开挖后": "应按原有道路或绿化进行恢复,管线尽量敷设于人行道上,不影响后续的绿化园林施工。" - } + "技术要求": { + "门禁管理系统": { + "门禁控制器": { + "系统架构": "1.系统采用 CS架构,支持 Web端登录,支持远程软硬件重启升级、维护、管理。", + "联网方式": "2.★支持 TCP/IP、4G、RS485联网方式、有线与无线(WIFI)可自动切换 ,控制器支持百台到上千台设备组网,需满足大楼多门点的管理数量要求。", + "安装方式": "3.★安装方式支持壁挂安装。", + "开门方式": "4.★支持卡、密码、首卡、双卡、主卡/副卡、胁迫码、多卡分组、指纹识别+中心确认等开门方式。全面支持读卡器、指纹、人脸、指静脉、RS485识读设备的混合接入。" }, + "出门按钮": { + "安装方式": "标准 86底盒安装方式,支持常开,常闭方式", + "结构": "塑料面板", + "性能": "最大耐电流 1.25A电压 250V", + "服务要求": "产品 需全 国联 保,享 受三 包服 务,保 修期: 3年。" + }, + "单门电磁锁": { + "1)通电上锁,断电开锁,开门时间可调节。": "1)通电上锁,断电开锁,开门时间可调节。", + "2)稳定性强,连续工作锁体无故障,使用更安全。": "2)稳定性强,连续工作锁体无故障,使用更安全。" + }, + "指纹仪": { + "传感器类型": "1.先进半导体传感器,全面领先于普通光学识别技术,更好的判别假指纹、湿指、污损破皮手指。", + "显示及提示": "2.直观的 LCD液晶显示及语音验证提示,配针孔摄像机,实现视频联动抓拍,手动布撤防,实现与监控中心门禁系统实现对讲(外置语音盒)。", + "验证方式": "3.支持 IC卡、指纹、卡加密码、编号多种组合验证方式。" + }, + "门禁服务器": { + "CPU": "1颗 intel至强系列处理器,核数≥12核,主频≥2.2GHz", + "内存": "32G*2 DDR4,16根内存插槽,最大支持扩展至 2TB内存", + "硬盘": "4块 600G 10K 2.5寸 SAS硬盘", + } + }, + "摄像系统": { + "佳能摄像机": { + "清晰度": "1k" + }, + "尼康录影机": { + "画质": "2k" + } + } + }, "商务要求": "", "服务要求": "", "其他要求": "" @@ -955,7 +617,16 @@ if __name__ == "__main__": "商务评分": {} } includes = ["基础信息", "资格审查", "商务评分", "技术评分", "无效标与废标项", "投标文件要求", "开评定标流程"] - res1,res2,res3=outer_post_processing(combined_data,includes) + good_list=[ + "门禁控制器", + "出门按钮", + "单门电磁锁", + "指纹仪", + "门禁服务器", + "佳能摄像机", + "尼康录影机" + ] + res1,res2,res3=outer_post_processing(combined_data,includes,good_list) # print(json.dumps(res2,ensure_ascii=False,indent=4)) print(json.dumps(res3,ensure_ascii=False,indent=4)) diff --git a/flask_app/general/纯技术参数要求提取.py b/flask_app/general/纯技术参数要求提取.py new file mode 100644 index 0000000..6d45721 --- /dev/null +++ b/flask_app/general/纯技术参数要求提取.py @@ -0,0 +1,48 @@ +from flask_app.general.通义千问long import upload_file +from flask_app.货物标.截取pdf货物标版 import truncate_pdf_main +from flask_app.货物标.技术参数要求提取 import get_technical_requirements + + +def extract_matching_keys(data_dict, good_list): + """ + 递归遍历data_dict,查找good_list中存在的键,并将匹配的键及其值添加到结果字典中。 + + 参数: + - data_dict (dict): 要遍历的嵌套字典。 + - good_list (list): 包含要查找的键的列表。 + + 返回: + - dict: 包含所有匹配键及其值的字典。 + """ + result = {} + + def recurse(current_dict): + if isinstance(current_dict, dict): + for key, value in current_dict.items(): + if key in good_list: + result[key] = value + # 递归遍历子字典 + recurse(value) + elif isinstance(current_dict, list): + for item in current_dict: + recurse(item) + # 如果current_dict不是dict或list,则无需进一步处理 + + recurse(data_dict) + return result + +def get_technical_requirements_main(file_path,output_folder): + truncate_file=truncate_pdf_main(file_path,output_folder,1)[0] + file_id=upload_file(truncate_file) + final_res=get_technical_requirements(file_id) + # 安全地提取 "技术要求" 内部的字典内容 + if isinstance(final_res, dict) and '技术要求' in final_res and isinstance(final_res['技术要求'], dict): + technical_requirements = final_res['技术要求'] + good_list = technical_requirements.pop('货物列表', []) # 如果 '货物列表' 不存在,返回 [] + return extract_matching_keys(technical_requirements,good_list) + else: + return final_res +if __name__ == "__main__": + file_path="C:\\Users\\Administrator\\Desktop\\fsdownload\\217754b7-3efd-41b2-806b-0b5b1bc98904\\ztbfile.pdf" + output_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1\\tmp" + # res=get_technical_requirements_main(truncate_file,output_folder) \ No newline at end of file diff --git a/flask_app/general/读取文件/format_amout.py b/flask_app/general/读取文件/format_amout.py deleted file mode 100644 index ef8c625..0000000 --- a/flask_app/general/读取文件/format_amout.py +++ /dev/null @@ -1,40 +0,0 @@ -import re - - -def format_amount(original_amount): - """ - 格式化金额字符串 - - 参数: - extracted_text (str): 输入的文本字符串 - - 返回: - str: 格式化后的金额字符串 - """ - # amount_str = "未解析到招标项目预算" - # 1. 删除所有空格 - amount_str = ''.join(original_amount.split()) - - # 匹配"万元"模式 - wan_pattern = r"(\d+\.?\d*)\s*万元" - wan_match = re.search(wan_pattern, amount_str) - - # 匹配"元"模式 - yuan_pattern = r"(\d+\.?\d*)\s*元" - yuan_match = re.search(yuan_pattern, amount_str) - - if wan_match: - # 如果找到"万元",将其乘以10000并格式化 - value = float(wan_match.group(1)) * 10000 - amount_str = "{:.0f}".format(value) - elif yuan_match: - # 找到"元",直接获取该数字并格式化 - value = float(yuan_match.group(1)) - amount_str = "{:.0f}".format(value) - - return amount_str - -input_test=["RMB100.01万元威威"] -for i in input_test: - formatted=format_amount(i) - print(formatted) \ No newline at end of file diff --git a/flask_app/main/start_up.py b/flask_app/main/start_up.py index 37f9a77..e73963f 100644 --- a/flask_app/main/start_up.py +++ b/flask_app/main/start_up.py @@ -11,7 +11,7 @@ from flask_app.main.download import download_file from flask_app.general.post_processing import outer_post_processing from flask_app.main.工程标解析main import engineering_bid_main from flask_app.货物标.货物标解析main import goods_bid_main -from flask_app.货物标.技术参数要求提取 import get_technical_requirements_main +from flask_app.general.纯技术参数要求提取 import get_technical_requirements_main app = Flask(__name__) class CSTFormatter(logging.Formatter): @@ -160,6 +160,7 @@ def validate_request(default_zb_type=1): @app.route('/procurement_reqs', methods=['POST']) def get_procurement_reqs(): logger = g.logger + output_folder=g.output_folder file_url, zb_type = validate_request() if isinstance(file_url, tuple): # Check if the returned value is an error response return file_url @@ -172,7 +173,14 @@ def get_procurement_reqs(): 'message': 'This endpoint only supports zb_type 2 (procurement requirements)' }), 400 else: + final_res_path=os.path.join(output_folder,'final_result.json') response = download_and_process_file_for_procurement(file_url) + try: + with open(final_res_path, 'w', encoding='utf-8') as json_file: + json.dump(final_res_path, json_file, ensure_ascii=False, indent=4) + logger.info(f"摘取后的数据已保存到 '{final_res_path}'") + except IOError as e: + logger.error(f"保存JSON文件时出错: {e}") return jsonify({ 'message': 'procurement_reqs processed successfully', 'filename': "filename", @@ -378,8 +386,6 @@ def process_and_stream(file_url, zb_type): } yield f"data: {json.dumps(response, ensure_ascii=False)}\n\n" - # 日志记录已合并数据 - logger.info(f"合并后的数据: {json.dumps(combined_data, ensure_ascii=False, indent=4)}") # **保存 combined_data 到 output_folder 下的 'final_result.json'** output_json_path = os.path.join(output_folder, 'final_result.json') diff --git a/flask_app/testdir/test3.py b/flask_app/testdir/test3.py index d97fb00..4d29483 100644 --- a/flask_app/testdir/test3.py +++ b/flask_app/testdir/test3.py @@ -1,79 +1,84 @@ -import re -from unittest.mock import Mock +def extract_matching_keys(data_dict, good_list): + """ + 递归遍历data_dict,查找good_list中存在的键,并将匹配的键及其值添加到结果字典中。 -def clean_page_content(text, common_header): - # 模拟清理页面内容的函数 - return text.replace(common_header, '') + 参数: + - data_dict (dict): 要遍历的嵌套字典。 + - good_list (list): 包含要查找的键的列表。 -def extract_pages_tobidders_notice(pdf_document, begin_pattern, end_pattern, begin_page, common_header): - start_page = None - mid_page = None - end_page = None - for i, page in enumerate(pdf_document.pages): - text = page.extract_text() or "" - cleaned_text = clean_page_content(text, common_header) - if start_page is None and re.search(begin_pattern, cleaned_text) and i > begin_page: - start_page = i - if start_page is not None and mid_page is None and re.search(r'^一\s*[、.]\s*(说\s*明|总\s*则)', cleaned_text): - mid_page = i - if start_page is not None and mid_page is not None and re.search(end_pattern, cleaned_text) and i > mid_page: - end_page = i - break - return start_page, mid_page, end_page + 返回: + - dict: 包含所有匹配键及其值的字典。 + """ + result = {} -# 创建模拟的PDF文档 -def create_mock_pdf(page_contents): - pdf_mock = Mock() - pdf_mock.pages = [Mock(extract_text=lambda: content) for content in page_contents] - return pdf_mock + def recurse(current_dict): + if isinstance(current_dict, dict): + for key, value in current_dict.items(): + if key in good_list: + result[key] = value + # 递归遍历子字典 + recurse(value) + elif isinstance(current_dict, list): + for item in current_dict: + recurse(item) + # 如果current_dict不是dict或list,则无需进一步处理 -# 测试用例 -def test_extract_pages(): - # 测试用例1:正常情况 - pdf1 = create_mock_pdf([ - "Page 0", - "第一章 投标人须知", - "其他内容", - "一、说明", - "更多内容", - "结束标记" - ]) - result1 = extract_pages_tobidders_notice(pdf1, r'第.+章\s*投标人须知', r'结束标记', -1, '') - print("Test Case 1:", result1) # 期望输出:(1, 3, 5) + recurse(data_dict) + return result - # 测试用例2:没有中间页 - pdf2 = create_mock_pdf([ - "Page 0", - "第一章 投标人须知", - "其他内容", - "结束标记" - ]) - result2 = extract_pages_tobidders_notice(pdf2, r'第.+章\s*投标人须知', r'结束标记', -1, '') - print("Test Case 2:", result2) # 期望输出:(1, None, 3) +# 示例数据 +data_dict = { + "门禁管理系统": { + "门禁控制器": { + "系统架构": "1.系统采用 CS架构,支持 Web端登录,支持远程软硬件重启升级、维护、管理。", + "联网方式": "2.★支持 TCP/IP、4G、RS485联网方式、有线与无线(WIFI)可自动切换 ,控制器支持百台到上千台设备组网,需满足大楼多门点的管理数量要求。", + "安装方式": "3.★安装方式支持壁挂安装。", + "开门方式": "4.★支持卡、密码、首卡、双卡、主卡/副卡、胁迫码、多卡分组、指纹识别+中心确认等开门方式。全面支持读卡器、指纹、人脸、指静脉、RS485识读设备的混合接入。" + }, + "出门按钮": { + "安装方式": "标准 86底盒安装方式,支持常开,常闭方式", + "结构": "塑料面板", + "性能": "最大耐电流 1.25A电压 250V", + "服务要求": "产品 需全 国联 保,享 受三 包服 务,保 修期: 3年。" + }, + "单门电磁锁": { + "1)通电上锁,断电开锁,开门时间可调节。": "1)通电上锁,断电开锁,开门时间可调节。", + "2)稳定性强,连续工作锁体无故障,使用更安全。": "2)稳定性强,连续工作锁体无故障,使用更安全。" + }, + "指纹仪": { + "传感器类型": "1.先进半导体传感器,全面领先于普通光学识别技术,更好的判别假指纹、湿指、污损破皮手指。", + "显示及提示": "2.直观的 LCD液晶显示及语音验证提示,配针孔摄像机,实现视频联动抓拍,手动布撤防,实现与监控中心门禁系统实现对讲(外置语音盒)。", + "验证方式": "3.支持 IC卡、指纹、卡加密码、编号多种组合验证方式。" + }, + "门禁服务器": { + "CPU": "1颗 intel至强系列处理器,核数≥12核,主频≥2.2GHz", + "内存": "32G*2 DDR4,16根内存插槽,最大支持扩展至 2TB内存", + "硬盘": "4块 600G 10K 2.5寸 SAS硬盘" + } + }, + "摄像系统": { + "佳能摄像机": { + "清晰度": "1k" + }, + "尼康录影机": { + "画质": "2k" + } + } +} - # 测试用例3:使用"总则"而不是"说明" - pdf3 = create_mock_pdf([ - "Page 0", - "第一章 投标人须知", - "其他内容", - "一、总则", - "更多内容", - "结束标记" - ]) - result3 = extract_pages_tobidders_notice(pdf3, r'第.+章\s*投标人须知', r'结束标记', -1, '') - print("Test Case 3:", result3) # 期望输出:(1, 3, 5) +good_list = [ + "门禁控制器", + "出门按钮", + "单门电磁锁", + "指纹仪", + "门禁服务器", + "佳能摄像机", + "尼康录影机" +] - # 测试用例4:中间页格式变化 - pdf4 = create_mock_pdf([ - "Page 0", - "第一章 投标人须知", - "其他内容", - "一.说 明", - "更多内容", - "结束标记" - ]) - result4 = extract_pages_tobidders_notice(pdf4, r'第.+章\s*投标人须知', r'结束标记', -1, '') - print("Test Case 4:", result4) # 期望输出:(1, 3, 5) +# 使用函数提取匹配的键 +filtered_dict = extract_matching_keys(data_dict, good_list) -# 运行测试 -test_extract_pages() \ No newline at end of file +# 打印结果 +import pprint +pprint.pprint(filtered_dict) diff --git a/flask_app/货物标/技术参数要求提取.py b/flask_app/货物标/技术参数要求提取.py index 07b77de..8303c7d 100644 --- a/flask_app/货物标/技术参数要求提取.py +++ b/flask_app/货物标/技术参数要求提取.py @@ -162,23 +162,11 @@ def test_all_files_in_folder(input_folder, output_folder): except Exception as e: print(f"处理文件 {file_path} 时出错: {e}") -def get_technical_requirements_main(file_path,output_folder): - truncate_file=truncate_pdf_main(file_path,output_folder,1)[0] - print(truncate_file) - file_id=upload_file(truncate_file) - final_res=get_technical_requirements(file_id) - # 安全地提取 "技术要求" 内部的字典内容 - if isinstance(final_res, dict) and '技术要求' in final_res and isinstance(final_res['技术要求'], dict): - return final_res['技术要求'] - else: - return final_res if __name__ == "__main__": truncate_file="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\广水农商行门禁控制主机及基础验证设备采购项目——磋商文件(定稿)(三次)_procurement.pdf" - # truncate_file="C:\\Users\\Administrator\\Desktop\\fsdownload\\217754b7-3efd-41b2-806b-0b5b1bc98904\\ztbfile.pdf" output_folder="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\tmp" file_id = upload_file(truncate_file) res=get_technical_requirements(file_id) - # res=get_technical_requirements_main(truncate_file,output_folder) json_string = json.dumps(res, ensure_ascii=False, indent=4) print(json_string) # input_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1" diff --git a/flask_app/货物标/货物标解析main.py b/flask_app/货物标/货物标解析main.py index 23fd732..e0cf28e 100644 --- a/flask_app/货物标/货物标解析main.py +++ b/flask_app/货物标/货物标解析main.py @@ -143,12 +143,24 @@ def post_process_baseinfo(base_info): - tuple: (处理后的 base_info, good_list) """ try: + pure_base_info = base_info.get("基础信息", {}) # 尝试提取 '货物列表',若中间某个键不存在,返回 good_list=[] - logger.info("hhhhhhhhhhhhhhhhhh") - logger.info(json.dumps(base_info,ensure_ascii=False,indent=4)) - procurement_reqs = base_info.get('采购要求', {}) + procurement_reqs = pure_base_info.get('采购要求', {}) technical_requirements = procurement_reqs.get('技术要求', {}) good_list = technical_requirements.pop('货物列表', []) # 如果 '货物列表' 不存在,返回 [] + + # 删除 '货物列表' 后更新原始的 base_info + if '技术要求' in procurement_reqs and not technical_requirements: + # 若技术要求为空,删除该键 + procurement_reqs.pop('技术要求') + + if '采购要求' in pure_base_info and not procurement_reqs: + # 若采购要求为空,删除该键 + pure_base_info.pop('采购要求') + + # 更新基础信息 + base_info['基础信息'] = pure_base_info + logger.info(f"Extracted good_list: {good_list}") return base_info, good_list except Exception as e: @@ -210,7 +222,7 @@ def goods_bid_main(output_folder, file_path, file_type, unique_id): yield json.dumps({'good_list': transform_json_values(collected_good_list)}, ensure_ascii=False) #广水市 2022 年义务教育学校多媒体补充采购项目 资格审查有问题 -#TODO:区分output目录 陕西省公安厅交通警察总队高速公路交通安全智能感知巡查系统项目 (1)_tobidders_notice_part2.pdf提取有问题 #一包二包问题 107国道 #日期格式统一 +#TODO:区分output目录 陕西省公安厅交通警察总队高速公路交通安全智能感知巡查系统项目 (1)_tobidders_notice_part2.pdf提取有问题 #一包二包问题 107国道 #good_list 金额 截取上下文 if __name__ == "__main__": import time