From 2ad1bff5f3b162a4904fb0cb7cfc32a3cbf21a8b Mon Sep 17 00:00:00 2001 From: zy123 <646228430@qq.com> Date: Fri, 20 Sep 2024 18:01:48 +0800 Subject: [PATCH] 9.20 --- flask_app/货物标/test.py | 116 ++++++++-- flask_app/货物标/test3.py | 42 ++++ flask_app/货物标/提示词/prompt1.txt | 322 ++++++++++++++++++++++++++++ flask_app/货物标/货物标截取pdf.py | 133 +++++++++--- 4 files changed, 558 insertions(+), 55 deletions(-) create mode 100644 flask_app/货物标/test3.py diff --git a/flask_app/货物标/test.py b/flask_app/货物标/test.py index 7982ce4..bf7f23f 100644 --- a/flask_app/货物标/test.py +++ b/flask_app/货物标/test.py @@ -1,31 +1,101 @@ +import json import re +#这个字典可能有嵌套,你需要遍历里面的键名,对键名作判断,而不是键值,具体是这样的:如果处于同一层级的键的数量>1并且键名全由数字或点号组成。那么就将这些序号键名全部删除,重新组织成一个字典格式的数据,你可以考虑用字符串列表来保持部分平级的数据 +#对于同级的键,如果数量>1且键名都统一,那么将键名去掉,用列表保持它们的键值 +#对于同一个字典中,可能存在若干键值对,若它们的键值都是""或者"/" 你就将它们的键值删去,它们的键名用字符串列表保存 +def is_numeric_key(key): + # 这个正则表达式匹配由数字、点、括号中的数字或单个字母(小写或大写)组成的字符串, + # 字母后跟数字,或数字后跟字母,单个字母后跟点,但不能是字母-数字-字母的组合 + pattern = r'^[\d.]+$|^\(\d+\)$|^(\d+)$|^[a-zA-Z]$|^[a-zA-Z]\d+$|^\d+[a-zA-Z]$|^[a-zA-Z]\.$' + return re.match(pattern, key) is not None +#TODO:如果键值中存在数字就不行 +#zbtest20也有问题 +def contains_number_or_index(key, value): + return (isinstance(value, (int, float)) or + (isinstance(value, str) and value.isdigit()) or + '序号' in key or + (isinstance(value, str) and re.search(r'\d+', value))) -def get_patterns_for_qualification(): - # begin_pattern 匹配以'资格审查'或'资格性检查'开始的标题,同时允许前面有章节编号和标题 - begin_pattern = re.compile( - r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(资格审查|资格性检查).*', re.MULTILINE) +def preprocess_dict(data): + if isinstance(data, dict): + if len(data) > 1: + # 检查是否所有值都是 "" 或 "/" + if all(v == "" or v == "/" for v in data.values()): + return list(data.keys()) + else: + processed = {} + for k, v in data.items(): + if not contains_number_or_index(k, v): + processed_v = preprocess_dict(v) + if processed_v != "": # 只添加非空值 + processed[k] = processed_v + return processed + else: + return {k: preprocess_dict(v) for k, v in data.items()} + elif isinstance(data, list): + return [preprocess_dict(item) for item in data] + else: + return data +def process_dict(data): + if not isinstance(data, dict): + return data - # end_pattern 匹配下一个章节的开始或以'附件'加数字开头的页 - end_pattern = re.compile( - r'^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+|附件\s*\d+', re.MULTILINE) + result = {} + numeric_keys = [] + non_numeric_keys = {} - return begin_pattern, end_pattern + for key, value in data.items(): + if is_numeric_key(key): + numeric_keys.append((key, value)) + else: + non_numeric_keys[key] = value -# 获取编译后的正则表达式 -begin_pattern, end_pattern = get_patterns_for_qualification() + # 处理数字键,不再要求数量>1 + if numeric_keys: + result['items'] = [process_dict(item[1]) for item in sorted(numeric_keys)] -# 示例字符串,用于测试正则表达式是否工作 -test_string = """ -第一章 资格审查 -资格性检查 -第二章 实施规范 -附件 4 使用说明 -""" + # 处理非数字键 + for key, value in non_numeric_keys.items(): + if isinstance(value, list) and len(value) > 1 and all(isinstance(item, dict) and len(item) == 1 for item in value): + common_key = next(iter(value[0].keys())) + if all(common_key in item and len(item) == 1 for item in value): + result[key] = [process_dict(item[common_key]) for item in value] + else: + result[key] = [process_dict(item) for item in value] + else: + result[key] = process_dict(value) -# 测试 begin_pattern -begin_matches = begin_pattern.findall(test_string) -print("Begin Matches:", begin_matches) + # 如果结果只包含'items'键,直接返回其值 + if len(result) == 1 and 'items' in result: + return result['items'] -# 测试 end_pattern -end_matches = end_pattern.findall(test_string) -print("End Matches:", end_matches) + return result + +# 测试代码 + +input_data = { + "符合性审查": { + "说明": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。", + "审查标准": [ + + + { + "序号": 9, + "内容": "未按要求提供加盖公章及签字(签章)的;" + }, + { + "序号": 1, + "内容": "符合招标文件第二章“投标人须知”中 39" + }, + { + "序号": 2, + "内容": "依据财库[2019]9号文的规定,招标文件采购清单中为“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的;" + }, + + ] + } +} +pred=preprocess_dict(input_data) +print(json.dumps(pred, ensure_ascii=False, indent=4)) +# processed_data = process_dict(pred) +# print(json.dumps(processed_data, ensure_ascii=False, indent=4)) \ No newline at end of file diff --git a/flask_app/货物标/test3.py b/flask_app/货物标/test3.py new file mode 100644 index 0000000..0a829d7 --- /dev/null +++ b/flask_app/货物标/test3.py @@ -0,0 +1,42 @@ +import re + +def contains_number_or_index(key, value): + return (isinstance(value, (int, float)) or + (isinstance(value, str) and value.isdigit()) or + '序号' in key or + (isinstance(value, str) and re.search(r'\d+', value))) + +def preprocess_dict(data): + if isinstance(data, dict): + if len(data) > 1: + # 检查是否所有值都是 "" 或 "/" + if all(v == "" or v == "/" for v in data.values()): + return list(data.keys()) + else: + processed = {} + for k, v in data.items(): + if not contains_number_or_index(k, v): + processed_v = preprocess_dict(v) + # 即使 processed_v 是空字符串,也保留键 + processed[k] = processed_v + return processed + else: + return {k: preprocess_dict(v) for k, v in data.items()} + elif isinstance(data, list): + return [preprocess_dict(item) for item in data] + else: + return data + +input_data = { + "具备法律、行政法规规定的其他条件的证明材料": { + "国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的": "则 必须提供取得国家有关主管部门行政许可的证明材料", + "未被列入“信用中国”网站(www.creditchina.gov.cn)信用服务栏失信被执行人、 重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单和“中国 政府采购”网站(www.ccgp.gov.cn)政府采购严重违法失信行为记录名单": "并 提供网页截图以证明", + "招标文件第一章“投标人资格要求”中有特殊要求的": "投标人应提供其符合特 殊要求的证明材料或者情况说明", + "不符合联合体投标相关规定和要求的": "", + "投标人认为需提供的其它相关资格证明材料": "", + "资格证明文件正本应为清晰彩色影印件且加盖单位公章": "" + } +} + +processed_data = preprocess_dict(input_data) +print(processed_data) diff --git a/flask_app/货物标/提示词/prompt1.txt b/flask_app/货物标/提示词/prompt1.txt index d4c4224..da69670 100644 --- a/flask_app/货物标/提示词/prompt1.txt +++ b/flask_app/货物标/提示词/prompt1.txt @@ -12,6 +12,9 @@ 这是一份货物标中采购要求部分的内容,请告诉我商务要求和其他要求是什么,请以json格式返回结果,外层键名分别是"商务要求"和"其他要求",内层键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减,注意你无需回答具体设备的技术要求,若相关要求不存在,在键值中填"未知"。 +"该招标文件中规定的资格性审查标准是怎样的?请以json格式给出,外层为'资格性审查',对于原文中的序号,你需要捕获它们之间的层级关系并生成嵌套键值对,你的回答无需包含序号,但其余内容要与原文一致,不可擅自总结删减,也不要回答符合性审查的内容。" + + "根据该文档中的评标办法前附表,请你列出该文件的技术标,商务标,投标报价评审标准以及它们对应的具体评分要求,若对应内容中存在其他信息,在键名如'技术标'中新增子键名'备注'存放该信息。如果评分内容不是这3个,则返回文档中给定的评分内容以及它的评分要求,都以json的格式返回结果。请不要回答有关形式、资格、响应性评审标准的内容") { @@ -151,4 +154,323 @@ } } +{ + "子项xxx": [ + { + "内容": "1. 国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的,则必须提供取得国家有关主管部门行政许可的证明材料。" + }, + { + "内容": "2. 未被列入”信用中国“网站(www.creditchina.gov.cn)信用服务栏失信被执行人、重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单和”中国政府采购“网站(www.ccgp.gov.cn)政府采购严重违法失信行为记录名单,并提供网页截图以证明;" + }, + { + "内容": "3. 招标文件第一章”投标人资格要求“中有特殊要求的,投标人应提供其符合特殊要求的证明材料或者情况说明;" + }, + { + "内容": "4. 不符合联合体投标相关规定和要求的;" + }, + { + "内容": "5. 投标人认为需提供的其它相关资格证明材料;" + }, + { + "内容": "6. 资格证明文件正本应为清晰彩色影印件且加盖单位公章。" + } + ] +} + +input_data = { + "资格性审查": { + "1": { + "参加政府采购活动的供应商应当具备政府采购法第二十二条第一款规定的条件,提供下列材料": { + "1.1": "法人或者其他组织的营业执照等证明文件,自然人身份证明", + "1.2": "财务状况报告,依法缴纳税收和社会保障资金的相关资料", + "1.3": "具备履行合同所必需的设备和专业技术能力的证明材料", + "1.4": "参加政府采购活动前 3 年内在经营活动中没有重大违法记录的书面声明", + "1.5": "具备法律、行政法规规定的其他条件的证明材料" + } + }, + "2": "单位负责人为同一人或者存在直接控股、管理关系的不同投标人,不得参加本项目同一合同项下的政府采购活动", + "3": "为本采购项目提供整体设计、规范编制或者项目管理、监理、检测等服务的,不得再参加本项目的其他招标采购活动", + "4": "未被列入”信用中国“网站(www.creditchina.gov.cn)失信被执行人、重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单的书面声明", + "5": "法定代表人携法定代表人身份证明和本人身份证原件或委托代理人携法定代表人授权委托书和本人身份证原件及委托人在本公司近三个月的缴纳社保证明" + } +} + + +{ + "资格性审查": { + "资格证明文件审查说明": "资格审查内容要求提供的相关证明材料,投标人应对应放入投标文件的“第一部分资格证明文件”中,否则,将会导致投标无效。所递交的资格证明文件出现不符合下列情形之一或不足以证明其符合下列情形之一的,应视为资格审查不合格,并按照无效投标处理。", + "应具备《政府采购法》第二十二条第一款规定的条件": { + "提供下列材料": { + "法人或者其他组织的营业执照等证明文件": { + "法人": { + "(1)企业法人(包括合伙企业)": "提供工商部门注册的有效“企业法人营业执照”或“营业执照”;", + "(2)事业单位法人": "提供有效的“事业单位法人证书”。" + }, + "其他组织": { + "(1)非企业专业服务机构": "提供执业许可证等证明文件;", + "(2)个体工商户": "提供有效的“个体工商户营业执照”。" + }, + "自然人": "提供有效的自然人身份证明。(仅限中国公民)" + }, + "财务状况报告": "依法缴纳税收和社会保障资金的相关材料:应严格按照附件格式提交“财务状况报告,依法缴纳税收和社会保障资金的声明函”", + "具备履行合同所必需的设备和专业技术能力的证明材料": { + "1.3.1": "提供具备足够数量的设施设备的证明材料;", + "1.3.2": "提供具备足够数量的技术人员的证明材料。" + }, + "参加政府采购活动前 3年内在经营活动中没有重大违法记录的声明": { + "1.4.1": "应严格按照附件格式提交“无重大违法记录的声明函”;", + "1.4.2": "政府采购法第二十二条第一款第五项所称重大违法记录,是指供应商因违法经营受到刑事处罚或者责令停产停业、吊销许可证或者执照、较大数额罚款等行政处罚;", + "1.4.3": "按照财政部《关于规范政府采购行政处罚有关问题的通知》的规定,各级人民政府财政部门依法对参加政府采购活动的供应商作出的禁止参加政府采购活动等行政处罚决定在全国范围内生效。" + }, + "具备法律、行政法规规定的其他条件的证明材料": { + "1.5.1": "国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的,则必须提供取得国家有关主管部门行政许可的证明材料。" + } + } + }, + "单位负责人为同一人或者存在直接控股、管理关系的不同投标人": "不得参加本项目同一合同项下的政府采购活动;应严格按照附件格式提交“未与单位负责人为同一人或者存在直接控股、管理关系 的其它投标人,参加同一合同项下的政府采购活动声明函”", + "为本采购项目提供整体设计、规范编制或者项目管理、监理、检测等服务的": "不得再参加本项目的其他招标采购活动;应严格按照附件格式提交“未为本采购项目提供整体设计、规范编制或者项目管理、 监理、检测等服务的声明函”", + "未被“信用中国”网站(www.creditchina.gov.cn)、“中国政府采购网”(www.ccgp.gov.cn)": "列入失信被执行人、重大税收违法案件当事人名单、政府采购严重违法失信行为记 录名单:应严格按照附件格式提交“未被列入记录名单的声明函”", + "落实政府采购政策应提供的资料": "", + "招标文件第一章“投标人资格要求”中有特殊要求的": "投标人应提供其符合特殊要 求的证明材料或者情况说明:", + "投标人认为需提供的其它相关资格证明材料": "", + "资格证明文件应为清晰影印件且加盖单位公章": "" + }, + "符合性审查": { + "说明": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。", + "审查标准": [ + { + "序号": 1, + "内容": "投标总报价超过项目(分包)预算金额或最高限价的;" + }, + { + "序号": 2, + "内容": "《投标书》、《法定代表人授权书》、《开标一览表(含明细)》未提供或不符合招标文件要求的;" + }, + { + "序号": 3, + "内容": "工期(服务期限)、质保期不符合招标文件要求的;" + }, + { + "序号": 4, + "内容": "出现两个或两个以上不同报价的;" + }, + { + "序号": 5, + "内容": "出现两个或两个以上投标方案的(招标文件中要求提供备选方案的除外);" + }, + { + "序号": 6, + "内容": "投标报价存在缺项、漏项的;" + }, + { + "序号": 7, + "内容": "投标有效期不足的;" + }, + { + "序号": 8, + "内容": "无法定代表人签字(签章)或签字人无法定代表人有效授权的;" + }, + { + "序号": 9, + "内容": "未按要求提供加盖公章及签字(签章)的;" + }, + { + "序号": 10, + "内容": "符合招标文件第二章“投标人须知”中 39条中规定情形,以分公司形式参与投标的,法定代表人授权书未由总公司法定代表人签字(签章)并加盖公章的;" + }, + { + "序号": 11, + "内容": "依据财库[2019]9号文的规定,招标文件采购清单中为“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的;" + }, + { + "序号": 12, + "内容": "所投货物是通过中国海关报关验放进入中国境内且产自关境外的(招标文件中注明已办理进口产品审核的除外);" + }, + { + "序号": 13, + "内容": "未提供所投货物(工程或服务)的具体参数值或功能表述,或原文复制招标文件的技术规格相关部分内容作为其投标文件的一部分的;" + }, + { + "序号": 14, + "内容": "不满足招标文件第三章“项目技术、服务和商务要求”中“★”号条款要求的;" + }, + { + "序号": 15, + "内容": "含有采购人不能接受的附加条件的;" + }, + { + "序号": 16, + "内容": "未按要求提供《符合性审查对照表》、《商务要求响应、偏离说明表》、《商务要求“★”号条款响应、偏离说明表》、《商务评议对照表》和《技术、服务要求响应、偏离说明表》、《技术、服务要求“★”号条款响应、偏离说明表》、《技术、服务评议对照表》的;" + }, + { + "序号": 17, + "内容": "不同投标人使用同一电脑(机器特征值一致:如 MAC地址等)或使用同一电子密钥,编制或上传电子投标文件;" + }, + { + "序号": 18, + "内容": "法律、法规和招标文件规定的其他无效投标情形。" + } + ] + } +} + +{ + "资格性审查": { + "资格证明文件审查": { + "法人或者其他组织的营业执照等证明文件": { + "法人": { + "企业法人(包括合伙企业)": "提供工商部门注册的有效“企业法人营业执照” 或“营业执照”", + "事业单位法人": "提供有效的“事业单位法人证书”" + }, + "其他组织": { + "非企业专业服务机构": "提供执业许可证等证明文件", + "个体工商户": "提供有效的“个体工商户营业执照”" + }, + "自然人": "提供有效的自然人身份证明。(仅限中国公民)" + }, + "财务状况报告": { + "法人": { + "提供经第三方审计的财务报告": "(完整的财务报告,包括“四表一注”, 即资产负债表、利润表、现金流量表、所有者权益变动表及其附注),或其基 本开户银行出具的资信证明" + }, + "部分其他组织和自然人": "没有经第三方审计的财务报告的,可以提供银行出 具的资信证明", + "投标人没有经第三方审计的财务报告和资信证明时": "也可以提供财政部门认 可的政府采购专业担保机构出具的投标担保函" + }, + "依法缴纳税收和社会保障资金的相关材料": { + "法人": { + "税务登记证(国税、地税或多证合一)": "", + "参加政府采购活动前一段时间内缴纳增值税、营业税和企业所得税的凭据": "", + "社会保险登记证(或多证合一)": "", + "参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)": "" + }, + "其他组织和自然人": { + "参加政府采购活动前一段时间内缴纳税收的凭据": "", + "参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)": "" + }, + "依法免税或不需要缴纳社会保险资金的投标人": "提供其依法免税或不需要缴纳社会保险资金的相关证明文件" + }, + "具备履行合同所必需的设备和专业技术能力的证明材料": { + "提供具备足够数量的设施设备的证明材料": "", + "提供具备足够数量的技术人员的证明材料": "" + }, + "参加政府采购活动前 3年内在经营活动中没有重大违法记录的书面声明": { + "应严格按照附件格式提交“参加政府采购活动前三年内在经营活动中没有重大 违法记录的书面声明函”": "", + "政府采购法第二十二条第一款第五项所称重大违法记录": "是指供应商因违法经 营受到刑事处罚或者责令停产停业、吊销许可证或者执照、较大数额罚款等行政处罚", + "按照财政部《关于规范政府采购行政处罚有关问题的通知》的规定": "各级人民 政府财政部门依法对参加政府采购活动的供应商作出的禁止参加政府采购活动等行政 处罚决定在全国范围内生效" + }, + "具备法律、行政法规规定的其他条件的证明材料": { + "国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的": "则 必须提供取得国家有关主管部门行政许可的证明材料", + "未被列入“信用中国”网站(www.creditchina.gov.cn)信用服务栏失信被执行人、 重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单和“中国 政府采购”网站(www.ccgp.gov.cn)政府采购严重违法失信行为记录名单": "并 提供网页截图以证明", + "招标文件第一章“投标人资格要求”中有特殊要求的": "投标人应提供其符合特 殊要求的证明材料或者情况说明", + "不符合联合体投标相关规定和要求的": "", + "投标人认为需提供的其它相关资格证明材料": "", + "资格证明文件正本应为清晰彩色影印件且加盖单位公章": "" + } + } + }, + "符合性审查": { + "描述": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。", + "无效投标处理情形": [ + "投标总报价超过项目(分包)预算金额或最高限价的", + "《投标书》、《法定代表人授权书》、《开标一览表》、《投标报价明细表》未提供或不符合招标文件要求的", + "工期(服务期限)、质保期不符合招标文件要求的", + "出现两个或两个以上不同报价的", + "出现两个或两个以上投标方案的(招标文件中要求提供备选方案的除外)", + "投标报价存在缺项、漏项的", + "投标有效期不足的", + "无法定代表人签字(签章)或签字人无法定代表人有效授权的", + "正本未按要求提供加盖公章及签字(签章)原件的", + "符合招标文件第二章“投标人须知”中 40条中规定情形,以分公司形式参与投标的,法定代表人授权书未由总公司法定代表人签字(签章)并加盖公章的", + "未按要求提供招标文件第二章“十、其他注意事项”中规定的书面声明的", + "所投货物是通过中国海关报关验放进入中国境内且产自关境外的(招标文件中注明已办理进口产品审核的除外)", + "依据财库[2019]9号文的规定,招标文件采购清单中注明“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的", + "未提供所投货物(工程或服务)的具体参数值或功能表述,或完全原文复制招标文件的技术规格相关部分内容作为其投标文件的一部分的", + "不满足招标文件第三章“项目技术、服务和商务要求”中“★”号条款要求的", + "含有采购人不能接受的附加条件的", + "未按要求提供《符合性审查对照表》、《商务要求响应、偏离说明表》、《商务要求“★”号条款响应、偏离说明表》、《商务评议对照表》和《技术、服务要求响应、偏离说明表》、《技术、服务要求“★”号条款响应、偏离说明表》、《技术、服务评议对照表》的", + "法律、法规和招标文件规定的其他无效投标情形" + ] + } +} + +{ + "资格性审查": { + "资格证明文件审查": [ + [ + "应具备《政府采购法》第二十二条第一款规定的条件,提供下列材料:" + ], + { + "法人或者其他组织的营业执照等证明文件,自然人的身份证明(投标人根据自身情况提供对应的证明材料)": [ + { + "法人": [ + "企业法人(包括合伙企业):提供工商部门注册的有效“企业法人营业执照” 或“营业执照”;", + "事业单位法人:提供有效的“事业单位法人证书”。" + ] + }, + { + "其他组织": [ + "非企业专业服务机构:提供执业许可证等证明文件;", + "个体工商户:提供有效的“个体工商户营业执照”。" + ] + }, + "自然人:提供有效的自然人身份证明。(仅限中国公民)" + ] + }, + { + "财务状况报告,依法缴纳税收和社会保障资金的相关材料(投标人根据自身情况提供对应的证明材料)": [ + { + "法人": [ + "税务登记证(国税、地税或多证合一);", + "参加政府采购活动前一段时间内缴纳增值税、营业税和企业所得税的凭据;", + "社会保险登记证(或多证合一);", + "参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)。" + ], + "其他组织和自然人": [ + "参加政府采购活动前一段时间内缴纳税收的凭据;", + "参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)。" + ], + "依法免税或不需要缴纳社会保险资金的投标人": "提供其依法免税或不需要缴纳社会保险资金的相关证明文件。" + } + ] + }, + { + "具备履行合同所必需的设备和专业技术能力的证明材料": [ + "提供具备足够数量的设施设备的证明材料;", + "提供具备足够数量的技术人员的证明材料。" + ] + }, + { + "参加政府采购活动前 3年内在经营活动中没有重大违法记录的书面声明": [ + "应严格按照附件格式提交“参加政府采购活动前三年内在经营活动中没有重大 违法记录的书面声明函”;", + "政府采购法第二十二条第一款第五项所称重大违法记录,是指供应商因违法经 营受到刑事处罚或者责令停产停业、吊销许可证或者执照、较大数额罚款等行政处罚;", + "按照财政部《关于规范政府采购行政处罚有关问题的通知》的规定,各级人民 政府财政部门依法对参加政府采购活动的供应商作出的禁止参加政府采购活动等行政 处罚决定在全国范围内生效。" + ] + }, + "具备法律、行政法规规定的其他条件的证明材料:" + ] + }, + "符合性审查": { + "描述": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。", + "无效投标处理情形": [ + "投标总报价超过项目(分包)预算金额或最高限价的", + "《投标书》、《法定代表人授权书》、《开标一览表》、《投标报价明细表》未提供或不符合招标文件要求的", + "工期(服务期限)、质保期不符合招标文件要求的", + "出现两个或两个以上不同报价的", + "出现两个或两个以上投标方案的(招标文件中要求提供备选方案的除外)", + "投标报价存在缺项、漏项的", + "投标有效期不足的", + "无法定代表人签字(签章)或签字人无法定代表人有效授权的", + "正本未按要求提供加盖公章及签字(签章)原件的", + "符合招标文件第二章“投标人须知”中 40条中规定情形,以分公司形式参与投标的,法定代表人授权书未由总公司法定代表人签字(签章)并加盖公章的", + "未按要求提供招标文件第二章“十、其他注意事项”中规定的书面声明的", + "所投货物是通过中国海关报关验放进入中国境内且产自关境外的(招标文件中注明已办理进口产品审核的除外)", + "依据财库[2019]9号文的规定,招标文件采购清单中注明“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的", + "未提供所投货物(工程或服务)的具体参数值或功能表述,或完全原文复制招标文件的技术规格相关部分内容作为其投标文件的一部分的", + "不满足招标文件第三章“项目技术、服务和商务要求”中“★”号条款要求的", + "含有采购人不能接受的附加条件的", + "未按要求提供《符合性审查对照表》、《商务要求响应、偏离说明表》、《商务要求“★”号条款响应、偏离说明表》、《商务评议对照表》和《技术、服务要求响应、偏离说明表》、《技术、服务要求“★”号条款响应、偏离说明表》、《技术、服务评议对照表》的", + "法律、法规和招标文件规定的其他无效投标情形" + ] + } +} + diff --git a/flask_app/货物标/货物标截取pdf.py b/flask_app/货物标/货物标截取pdf.py index c6ab823..64ee4f5 100644 --- a/flask_app/货物标/货物标截取pdf.py +++ b/flask_app/货物标/货物标截取pdf.py @@ -4,6 +4,7 @@ import os # 用于文件和文件夹操作 from flask_app.main.format_change import docx2pdf + def clean_page_content(text, common_header): # 首先删除抬头公共部分 if common_header: # 确保有公共抬头才进行替换 @@ -67,29 +68,88 @@ def convert_to_pdf(file_path): return docx2pdf(file_path) return file_path +def judge_file_exist(original_path, new_suffix): + # 提取目录路径和原始文件名 + directory = os.path.dirname(original_path) + original_filename = os.path.basename(original_path) + + # 替换文件名中的旧后缀为新后缀 + # 假设原始文件名格式为 '2-招标文件_qualification.pdf' + # 需要替换 '_qualification' 部分为 '_qualification2' + new_filename = original_filename.replace("_qualification1", f"_{new_suffix}") + new_filename = new_filename.replace("_qualification2", f"_{new_suffix}") + # 生成新的文件路径 + new_file_path = os.path.join(directory, new_filename) + + # 检查新文件是否存在 + if os.path.isfile(new_file_path): + return new_file_path + else: + return None +def merge_pdfs(paths, output_path): + pdf_writer = PdfWriter() + last_page_text = None # 用于存储上一个PDF的最后一页的文本 + + for path in paths: + pdf_reader = PdfReader(path) + pages = pdf_reader.pages + start_index = 0 # 从第一页开始添加 + + # 如果这不是第一个文件,并且有上一个文件的最后一页文本 + if last_page_text is not None and len(pages) > 0: + current_first_page_text = pages[0].extract_text() if pages[0].extract_text() else "" + # 比较当前文件的第一页和上一个文件的最后一页的文本 + if current_first_page_text == last_page_text: + start_index = 1 # 如果相同,跳过当前文件的第一页 + + # 添加当前PDF的页面到写入器 + for page in range(start_index, len(pages)): + pdf_writer.add_page(pages[page]) + + # 更新last_page_text为当前PDF的最后一页的文本 + if len(pages) > 0: + last_page_text = pages[-1].extract_text() if pages[-1].extract_text() else "" + + # 写入合并后的PDF到文件 + with open(output_path, 'wb') as out: + pdf_writer.write(out) +def merge_and_cleanup(output_pdf_path, suffix_to_merge): + another_file_path = judge_file_exist(output_pdf_path, suffix_to_merge) + if another_file_path: + paths = [output_pdf_path, another_file_path] # 需要合并的 PDF 文件路径 + merge_pdfs(paths, output_pdf_path) + os.remove(another_file_path) + print(f"文件 {another_file_path} 已删除。") + +def process_files(file_path, output_folder, begin_pattern, begin_page, end_pattern, output_suffix): + pdf_path = convert_to_pdf(file_path) + output_pdf_path = extract_pages(pdf_path, output_folder, begin_pattern, begin_page, end_pattern, output_suffix) + if output_pdf_path: + if output_suffix == "qualification1": + merge_and_cleanup(output_pdf_path, "qualification3") + return output_pdf_path + return None def process_input(input_path, output_folder, begin_pattern, begin_page, end_pattern, output_suffix): if not os.path.exists(output_folder): os.makedirs(output_folder) generated_files = [] + + # 判断输入是目录还是单个文件,并统一处理 if os.path.isdir(input_path): - # 遍历文件夹内的所有PDF文件 - for file in os.listdir(input_path): - file_path = os.path.join(input_path, file) - if is_pdf_or_doc(file): - pdf_path = convert_to_pdf(file_path) - output_pdf_path = extract_pages(pdf_path, output_folder, begin_pattern, begin_page, end_pattern, - output_suffix) - if output_pdf_path: - generated_files.append(output_pdf_path) - elif os.path.isfile(input_path) and input_path.endswith(".pdf"): - # 处理单个PDF文件 - output_pdf_path = extract_pages(input_path, output_folder, begin_pattern, begin_page, end_pattern, - output_suffix) - if output_pdf_path: - generated_files.append(output_pdf_path) + for file_name in os.listdir(input_path): + file_path = os.path.join(input_path, file_name) + if is_pdf_or_doc(file_path): + result = process_files(file_path, output_folder, begin_pattern, begin_page, end_pattern, output_suffix) + if result: + generated_files.append(result) + elif os.path.isfile(input_path) and is_pdf_or_doc(input_path): + result = process_files(input_path, output_folder, begin_pattern, begin_page, end_pattern, output_suffix) + if result: + generated_files.append(result) else: print("提供的路径既不是文件夹也不是PDF文件。") + return generated_files @@ -113,11 +173,16 @@ def extract_pages(pdf_path, output_folder, begin_pattern, begin_page, end_patter try: common_header = extract_common_header(pdf_path) pdf_document = PdfReader(pdf_path) + exclusion_pattern = None + if output_suffix=="qualification1": + exclusion_pattern=re.compile(r'文件的构成|文件的组成|须对应|需对应|须按照|需按照|须根据|需根据') start_page, end_page = extract_pages_generic(pdf_document, begin_pattern, end_pattern, begin_page, - common_header) + common_header,exclusion_pattern) if start_page is None or end_page is None: print(f"first: {output_suffix} 未找到起始或结束页在文件 {pdf_path} 中!尝试备用提取策略。") return extract_pages_twice(pdf_path, output_folder, output_suffix, common_header) + elif output_suffix=="qualification1": + truncate_pdf_main(pdf_path,output_folder,2,"qualification3") return save_extracted_pages(pdf_document, start_page, end_page, pdf_path, output_folder, output_suffix) except Exception as e: print(f"Error processing {pdf_path}: {e}") @@ -143,19 +208,19 @@ def get_patterns_for_evaluation_method(): def get_patterns_for_qualification(): - # 原始匹配逻辑 - begin_pattern_original = re.compile( - r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(资格审查).*', re.MULTILINE) - end_pattern_original = re.compile( - r'^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+', re.MULTILINE) + # # 原始匹配逻辑 + # begin_pattern_original = re.compile( + # r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(资格审查).*', re.MULTILINE) + # end_pattern_original = re.compile( + # r'^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+', re.MULTILINE) # 新匹配逻辑 begin_pattern_new = re.compile( r'^资格性检查', re.MULTILINE) end_pattern_new = re.compile( - r'^附件\s*\d+', re.MULTILINE) + r'^附件\s*\d+|^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+', re.MULTILINE) - return (begin_pattern_original, end_pattern_original), (begin_pattern_new, end_pattern_new) + return begin_pattern_new, end_pattern_new def extract_pages_twice(pdf_path, output_folder, output_suffix, common_header): @@ -165,10 +230,10 @@ def extract_pages_twice(pdf_path, output_folder, output_suffix, common_header): if output_suffix == "procurement": patterns = [get_patterns_for_procurement()] - elif output_suffix == "evaluation_method" or output_suffix=="qualification2": + elif output_suffix == "evaluation_method" or output_suffix=="qualification2" or output_suffix=="qualification3": patterns = [get_patterns_for_evaluation_method()] - elif output_suffix == "qualification": - patterns = get_patterns_for_qualification() # This now returns a tuple of pattern pairs + elif output_suffix == "qualification1": + patterns = [get_patterns_for_qualification()] # This now returns a tuple of pattern pairs # Try each set of patterns until a valid range is found for pattern_pair in patterns: @@ -177,10 +242,14 @@ def extract_pages_twice(pdf_path, output_folder, output_suffix, common_header): if start_page is not None and end_page is not None: break if start_page is None or end_page is None: - if output_suffix == "qualification": + if output_suffix == "qualification1": print(f"second: {output_suffix} 未找到起始或结束页在文件 {pdf_path} 中!") print("third:尝试提取评分办法章节...") - return truncate_pdf_main(pdf_path,output_folder,2,"qualification2") + temp=truncate_pdf_main(pdf_path,output_folder,2,"qualification2") + if len(temp) > 0: + return temp[0] + else: + return None else: print(f"second: {output_suffix} 未找到起始或结束页在文件 {pdf_path} 中!") return "" @@ -222,13 +291,13 @@ def truncate_pdf_main(input_path, output_folder, selection, output_suffix="defau local_output_suffix = "evaluation_method" elif selection == 3: begin_pattern = re.compile( - r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(资格审查).*' + r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(资格审查).*', re.MULTILINE ) begin_page = 5 end_pattern = re.compile( - r'^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+' + r'^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+', re.MULTILINE ) - local_output_suffix = "qualification" + local_output_suffix = "qualification1" else: print("无效的选择") return None @@ -252,7 +321,7 @@ def truncate_pdf_multiple(input_path, output_folder): # TODO:交通智能系统和招标(1)(1)文件有问题 if __name__ == "__main__": - input_path = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\交通智能运行维护招标文件.pdf" + input_path = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\622二次视频会议磋商文件(1).pdf" output_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output3" # truncate_pdf_multiple(input_path,output_folder) selection = 3 # 例如:1 - 商务技术服务要求, 2 - 评标办法, 3 - 资格审查