|
@@ -881,7 +881,7 @@ class PREMPredict():
|
|
|
elif label in [2,3,4] and re.search('序号:\d+,\w{,2}候选', front):
|
|
|
label = 5
|
|
|
elif label == 0:
|
|
|
- if re.search('拟邀请$|受邀谈判方|流入方名称:$|拟选用单位:$', front): # 修复 626700009 二、拟选用单位:海南和泰消防技术服务有限公司。
|
|
|
+ if re.search('拟邀请$|受邀谈判方|流入方名称:$|拟选用单位:$|选择(建设|\w{,2})?服务单位:$', front): # 修复 626700009 二、拟选用单位:海南和泰消防技术服务有限公司。 632486555 选择建设服务单位:四川富吉兴工程管理有限公司,
|
|
|
label = 2
|
|
|
values[label] = 0.501
|
|
|
elif re.search('(发布(人|方|单位|机构|组织|用户|业主|主体|部门|公司|企业)|组织(单位|人|方|机构)?|(采购|招标|发布)机构)(名称)?[是为:]+', front) and is_agency(entity.entity_text):
|
|
@@ -895,7 +895,7 @@ class PREMPredict():
|
|
|
elif re.search(',单位名称:$', front) and re.search('^,(中标|中选)价格', behind):
|
|
|
label = 2
|
|
|
values[label] = 0.501
|
|
|
- elif re.search('选择$|挂牌业务:$|评价单位:$|代建单位:$|报价(人|单位):$|实施主体:$', front): # 修复 92729222 所以我院只能选择 西门子公司 官方维修渠道供货及维修 预测为招标人 75044917 网上挂牌业务:汝阳县公共资源交易中心,联系人:杨先生 评价机构的名称和联系方式 73326818 评价单位:湖南知成环保服务有限公司 119136658 代建单位: 杭州千岛湖房地产开发有限公司 ,招标方式:公开招标 90007873 沟临时改线工程,报价单位: 莆田市涵江区茂发建筑有限公司 。 626694010 实施主体:融安县奇点农业发展有限公司 ,建设内容:1.购买果蔬多功能
|
|
|
+ elif re.search('选择$|挂牌业务:$|评价单位:$|代建单位:$|报价(人|单位):$|,实施主体:$', front): # 修复 92729222 所以我院只能选择 西门子公司 官方维修渠道供货及维修 预测为招标人 75044917 网上挂牌业务:汝阳县公共资源交易中心,联系人:杨先生 评价机构的名称和联系方式 73326818 评价单位:湖南知成环保服务有限公司 119136658 代建单位: 杭州千岛湖房地产开发有限公司 ,招标方式:公开招标 90007873 沟临时改线工程,报价单位: 莆田市涵江区茂发建筑有限公司 。 626694010 实施主体:融安县奇点农业发展有限公司 ,建设内容:1.购买果蔬多功能
|
|
|
label = 5
|
|
|
elif re.search('向\w{,4}$', front) and re.search('^反映', behind): # 修复 113239863 如有异议请于公示结束日期前向采购人 纪检监察部门 反映。
|
|
|
label = 5
|
|
@@ -935,7 +935,7 @@ class PREMPredict():
|
|
|
elif re.search('来源(单位)?:$', front):# and re.search('^,', behind): # 修复 472062585 项目采购-关于定制手机询比价采购中标公告,来源:深圳市网联安瑞网络科技有限公司 预测为中标
|
|
|
label = 0
|
|
|
values[label] = 0.5
|
|
|
- elif re.search('合同供方:?$|合同签约单位', front):
|
|
|
+ elif re.search('合同供方:?$|合同签约(单位|方):$|中标单位合同签订主体:$', front): # 632476647 八、合同签约方: 山东港信资本投资有限公司 /安阳钢铁股份有限公司 642339031 中标单位合同签订主体:新乡中新化工有限责任公司。
|
|
|
label = 0
|
|
|
values[label] = 0.5
|
|
|
elif re.search('现由$', front) and re.search('^作为\d个单位的牵头(单位|公司)?', behind): # 修复 469369884 站源批量预测错误 现由第七合同段保利长大工程有限公司作为6个单位的牵头单位,
|
|
@@ -950,11 +950,13 @@ class PREMPredict():
|
|
|
elif re.search('^为\w{,10}第二(成交|中标)单位', behind): # 中标预测错误,例:601143888 河南省创慧新材料科技有限公司为铸咀采购项目第二成交单位
|
|
|
label = 3
|
|
|
values[3] = 0.5
|
|
|
- elif re.search('中标单位,$|被确定为$', front): # 632523961 现通知:贵司被确定为广州地铁传媒有限公司贵阳地铁广告媒体服务项目(2025年)的执行单位。
|
|
|
+ elif re.search('中标单位,$|被确定为$|成交电商:$|如果?我方成功中选$', front): # 632523961 现通知:贵司被确定为广州地铁传媒有限公司贵阳地铁广告媒体服务项目(2025年)的执行单位。 # 609280615 万银政采平台 罗山县政采平台等成交电商都不是中标人 632380222 如我方成功中选 中国人民保险 采购项目,
|
|
|
label = 5
|
|
|
elif re.search('^为预备中标单位', behind):
|
|
|
label = 3
|
|
|
values[3] = 0.5
|
|
|
+ elif re.search(',中标人,$', front) and re.search('^\w{5,}', behind): # 修复 629482521 ,中标人,中国电建山东电建三公司山东发展杨庄集风电项目风力发电站GIS设备采,购项目:青岛特锐德电气股份有限公司,
|
|
|
+ label = 5
|
|
|
elif re.search('是否中标:是,供应商', front) and label == 5:
|
|
|
label = 2
|
|
|
values[label] = 0.9
|
|
@@ -1077,6 +1079,9 @@ class PREMPredict():
|
|
|
elif re.search('招标金额|限价|预算|控制价|拦标价', front) == None and re.search('预计约?为?$',
|
|
|
front): # 20241206纠正 565894149(预计约2500元)预测为预算
|
|
|
label = 2
|
|
|
+
|
|
|
+ elif re.search('挂网价((万?元))?:', front): # 修复 634316533 生产企业:洛阳顺势药业有限公司,挂网价(元):59.76,
|
|
|
+ label = 2
|
|
|
elif re.search('报价:预估不?含税总价[为:]$', front) and (label != 1 or values[label]<0.5):
|
|
|
label = 1
|
|
|
values[label] = 0.8
|
|
@@ -1534,7 +1539,7 @@ class RoleRulePredictor():
|
|
|
self.pattern_thirdTenderer_left = "(?P<thirdTenderer_left>(第[三3]名?(名|((中标|中选|中价|成交|候选)(候选)?(人|单位|机构|供应商|公司|银行))))(名称)?[::是为]+$|((评审结果|名次|排名|排序)[::]第?[三3]名?,?(投标(供应)?商|供应商)(名称)?[::]+$))"
|
|
|
self.pattern_thirdTenderer_right = "(?P<thirdTenderer_right>^[是为\(]第[三3](名|(中标|中选|中价|成交)(候选)?(人|单位|机构|供应商|公司|银行)))"
|
|
|
|
|
|
- self.candidate_left = "(?P<candidate_left>(((中[标选商]|成交|入围|入选)?候选|投标)(人|单位|机构|中介(服务)?机构|供应商|客户|方|公司|厂商|商家?|社会资本方?|银行)|服务单位|候选企业)(:?单位名称|:?名称|全称|(?盖\w{,5}章)?|如下|:?牵头人|[及与和](成交|中标)金额)?[::是为【]+$)"
|
|
|
+ self.candidate_left = "(?P<candidate_left>(((中[标选商]|成交|入围|入选)?候选|投标)(人|单位|机构|中介(服务)?机构|供应商|客户|方|公司|厂商|商家?|社会资本方?|银行)|服务单位|候选企业)(1.)?(:?单位名称|:?名称|全称|(?盖\w{,5}章)?|如下|:?牵头人|[及与和](成交|中标)金额)?[::是为【]+(1[.、])?$)"
|
|
|
|
|
|
self.pattern_left = [
|
|
|
self.pattern_tenderee_left_60,
|
|
@@ -1563,7 +1568,7 @@ class RoleRulePredictor():
|
|
|
|
|
|
self.SET_NOT_TENDERER = set(["人民政府","人民法院","中华人民共和国","人民检察院","评标委员会","中国政府","中国海关","中华人民共和国政府"])
|
|
|
|
|
|
- self.pattern_money_tenderee = re.compile("投?标?最高限价|采购计划金额|项目预算|招标金额|采购金额|项目金额|投资估算|采购(单位|人)委托价|招标限价|拦标价|预算金额|标底|总计|限额|资金来源,?[为:]+\w{2,4}资金|采购成本价|总费用约?为|(招标|采购)总?(规模|额度|资金)|资金来源|合同价暂定|包合计:$") # |建安费用 不作为招标金额
|
|
|
+ self.pattern_money_tenderee = re.compile("投?标?最高限价|采购计划金额|项目预算|招标金额|采购金额|项目金额|投资估算|采购(单位|人)委托价|招标限价|拦标价|预算金额|标底|总计|限额|资金来源,?[为:]+\w{2,4}资金|采购成本价|总费用约?为|(招标|采购)总?(规模|额度|资金)|资金来源|合同价暂定|包合计:$") # |建安费用 不作为招标金额 634252534 包合计:180,000.00 元
|
|
|
self.pattern_money_tenderer = re.compile("((合同|成交|中标|应付款|交易|投标|验收|订单)[)\)]?(综合)?(总?金额|结果|[单报总]?价))|标的基本情况|承包价|报酬(含税):|经评审的价格|报价不?含税") # 单写 总价 不能作为中标金额,很多表格有单价、总价
|
|
|
self.pattern_money_tenderer_whole = re.compile("(以金额.*中标)|中标供应商.*单价|以.*元(报价)?(中标|中选|成交)")
|
|
|
self.pattern_money_other = re.compile("代理费|服务费")
|
|
@@ -1798,7 +1803,7 @@ class RoleRulePredictor():
|
|
|
_label, _prob, _flag, kw = self.rule_predict(before, center, after, entity_text)
|
|
|
|
|
|
if _label == 5 and re.search(':(1[.、])?$', before) and re.search('^[、;,&/。]', after) and re.search('(监督|管理)(机构|部门|单位):', before)==None and re.search(
|
|
|
- '(中标|成交|中选))?(人|单位|供应商|银行|合作伙伴)?(公示)?(信息|情况|结果|如下)(公[示告]如下)?:|(遴选|寻源|采购|招标|竞价|议价|比选|委托|询比?价|比价|评选|谈判|邀标|邀请|洽谈|约谈|选取|抽取)结果(如下)(公[示告]如下)?:', list_sentence[s_index].sentence_text[:p_entity.wordOffset_begin]): # 补充召回 例:514053647 标段1:中国建设银行西安南大街支行,标段2:中国农业银行股份有限公司西安分行,
|
|
|
+ '(中标|成交|中选))?(人|单位|供应商|银行|合作伙伴)?(公示)?(信息|情况|结果|如下)(公[示告]如下)?:|(遴选|寻源|采购|招标|竞价|议价|比选|委托|询比?价|比价|评选|谈判|邀标|邀请|洽谈|约谈|选取|抽取)结果(如下)(公[示告]如下)?:|,中标人,', list_sentence[s_index].sentence_text[:p_entity.wordOffset_begin]): # 补充召回 例:514053647 标段1:中国建设银行西安南大街支行,标段2:中国农业银行股份有限公司西安分行,
|
|
|
_flag = True
|
|
|
_label = 2
|
|
|
_prob = 0.5
|
|
@@ -2568,7 +2573,7 @@ class RoleGrade():
|
|
|
|
|
|
class MoneyGrade():
|
|
|
def __init__(self):
|
|
|
- self.tenderee_money_left_9 = "(?P<tenderee_left_9>最高(投标)?限价)|控制价|拦标价"
|
|
|
+ self.tenderee_money_left_9 = "(?P<tenderee_left_9>最高(投标)?限价)|控制(价|金额)|拦标价"
|
|
|
self.tenderee_money_left_8 = "(?P<tenderee_left_8>预算|限价|起始|起拍|底价|标底)"
|
|
|
self.tenderer_money_left_9 = "(?P<tenderer_left_9>(中标|成交|合同|总报价))"
|
|
|
self.tenderer_money_left_8 = "(?P<tenderer_left_8>(投标|总价))"
|
|
@@ -2602,6 +2607,8 @@ class MoneyGrade():
|
|
|
_prob = max(0.5, _prob - 0.2)
|
|
|
entity.values[_label] = _prob + entity.values[_label] / 20
|
|
|
not_found = 0
|
|
|
+ if _label == 0 and float(entity.entity_text)<10000 and entity.values[_label] > 0.6: # 20250624 小金额预算概率降低 634252534 包合计才是真正的预算
|
|
|
+ entity.values[_label] = 0.6
|
|
|
# print('规则修改金额概率后:', entity.entity_text, entity.label, entity.values)
|
|
|
break
|
|
|
if not_found and entity.values[entity.label] > min_prob:
|
|
@@ -2981,6 +2988,7 @@ class ProductAttributesPredictor():
|
|
|
for td in tds:
|
|
|
# td_text = re.sub('\s+|…', ' ', td.get_text()).strip()
|
|
|
td_text = re.sub('…', '', td.get_text()).strip()
|
|
|
+ td_text = re.sub('\n+|\s+', ' ', td_text) # 20250626 去掉\n等避免存OTS后去掉转义导致json解析错误
|
|
|
td_text = td_text.replace("\x06", "").replace("\x05", "").replace("\x07", "").replace('\\', '/').replace('"', '') # 修复272144312 # 产品单价数量提取结果有特殊符号\ 气动执行装置备件\密封组件\NBR+PT
|
|
|
td_text = td_text.replace("(", "(").replace(")", ")").replace(':', ':')
|
|
|
tr_line.append(td_text)
|
|
@@ -3355,6 +3363,7 @@ class ProductAttributesPredictor():
|
|
|
total_product_money = 0
|
|
|
unit_price_list = [] # 单价列表,用于判断是否重复单价,避免多个表格重复提取造成合计产品价格错误。
|
|
|
total_price_list = [] # 总价列表,拥有判断是否为几行产品合计总价
|
|
|
+ budget_list = [] # 预算列表,用于统计所有产品预算
|
|
|
# print('表格数:', len(tables))
|
|
|
|
|
|
for i in range(len(tables)): # (len(tables)-1, -1, -1) 由从最后到前改为 前到后
|
|
@@ -3516,12 +3525,10 @@ class ProductAttributesPredictor():
|
|
|
headers_demand.append('_'.join(header_list2))
|
|
|
header_col.append('_'.join(tds))
|
|
|
i += 1
|
|
|
- # print('表头数量占行列数0.4倍不做内容匹配', set([re.sub('[::]','',td) for td in tds]) & self.header_set, tds)
|
|
|
continue
|
|
|
elif found_header:
|
|
|
if len(tds) > header_colnum or len(tds)-1<max([it for it in header_dic.values() if it!=""]): # 表头、属性列数不一致跳过
|
|
|
i += 1
|
|
|
- # print('表头、属性列数不一致跳过', len(tds), header_colnum, tds)
|
|
|
continue
|
|
|
id0 = header_dic.get('品目', "")
|
|
|
id1 = header_dic.get('名称', "")
|
|
@@ -3676,6 +3683,8 @@ class ProductAttributesPredictor():
|
|
|
unitPrice = str(unitPrice) if unitPrice != 0 and unitPrice<100000000 else ""
|
|
|
if budget != "":
|
|
|
budget, _money_unit = money_process(budget, header_list2[2])
|
|
|
+ if budget > 0:
|
|
|
+ budget_list.append(budget)
|
|
|
budget = str(budget) if budget != 0 and budget<50000000000 else ''
|
|
|
if total_price != "":
|
|
|
total_price, _money_unit = money_process(total_price, header_list[6])
|
|
@@ -3720,6 +3729,8 @@ class ProductAttributesPredictor():
|
|
|
unitPrice = str(unitPrice) if unitPrice != 0 and unitPrice<100000000 else ""
|
|
|
if budget != "":
|
|
|
budget, _money_unit = money_process(budget, header_list2[2])
|
|
|
+ if budget > 0:
|
|
|
+ budget_list.append(budget)
|
|
|
budget = str(budget) if budget != 0 and budget<50000000000 else ''
|
|
|
if total_price != "":
|
|
|
total_price, _money_unit = money_process(total_price, header_list[6])
|
|
@@ -3768,6 +3779,9 @@ class ProductAttributesPredictor():
|
|
|
i += 1
|
|
|
else:
|
|
|
i += 1
|
|
|
+ if i > 2 and len(set(tds)) in [2, 3] and re.search('订单总价', tds[0]) and re.search('\d+[\d,\.]*', tds[1]): # 修复 608217698 采购多项东西成交价不同,订单总价才是中标金额
|
|
|
+ money_, unit_ = money_process(tds[1], tds[0])
|
|
|
+ total_product_money = money_ if money_ > total_product_money else total_product_money
|
|
|
if len(total_price_list)>1 and len(set(total_price_list))/len(total_price_list)<=0.5: # 2023/7/27 总价一半以上重复的为多行一个总价,需去掉
|
|
|
# print('总价一半以上重复的为多行一个总价,需去掉', total_price_list)
|
|
|
for link in product_link: # 预防最后一列总价为所有产品总价,列补全后所有产品总价一样情况
|
|
@@ -3787,15 +3801,17 @@ class ProductAttributesPredictor():
|
|
|
if len(product_link)>0:
|
|
|
product_link = [{k:v for k,v in d.items() if v!=''} for d in product_link]
|
|
|
attr_dic = {'product_attrs':{'data':product_link, 'header':headers, 'header_col':header_col}}
|
|
|
+ total_budget = sum(budget_list) if len(budget_list) == len(product_link) else 0
|
|
|
else:
|
|
|
attr_dic = {'product_attrs': {'data': [], 'header': [], 'header_col': []}}
|
|
|
+ total_budget = 0
|
|
|
if len(demand_link)>0:
|
|
|
demand_link = [{k: v for k, v in d.items() if v != ''} for d in demand_link]
|
|
|
demand_dic = {'demand_info':{'data':demand_link, 'header':headers_demand, 'header_col':header_col}}
|
|
|
else:
|
|
|
demand_dic = {'demand_info':{'data':[], 'header':[], 'header_col':[]}}
|
|
|
# print('表格产品属性提取:', attr_dic)
|
|
|
- return [attr_dic, demand_dic], total_product_money
|
|
|
+ return [attr_dic, demand_dic], total_product_money, total_budget
|
|
|
|
|
|
def predict_without_table(self,product_attrs,list_sentences,list_entitys,codeName,prem, html='', page_time=""):
|
|
|
if len(prem[0]['prem'])==1:
|
|
@@ -6306,8 +6322,6 @@ class DistrictPredictor():
|
|
|
pro_ids, city_ids, dis_ids = self.merge_score(province_l, city_l, district_l, self.full_dic, self.short_dic, self.idx_dic)
|
|
|
big_area_1, pred_pro_1, pred_city_1, pred_dis_1, prob, max_score = self.get_final_addr(pro_ids, city_ids, dis_ids, self.idx_dic)
|
|
|
big_area, pred_pro, pred_city, pred_dis = big_area_1, pred_pro_1, pred_city_1, pred_dis_1
|
|
|
- # print('关键词1:', province_l, city_l, district_l)
|
|
|
- # print('分数:', pro_ids, city_ids, dis_ids, prob, max_score)
|
|
|
if pred_city_1 == "" or prob < 0.7 or max_score<2:
|
|
|
ree, addr = self.get_ree_addr(prem)
|
|
|
if ree in title:
|