瀏覽代碼

调整channel分类规则;调整extract.py 散乱代码封装为函数

lsm 3 年之前
父節點
當前提交
9a9bf43100
共有 3 個文件被更改,包括 165 次插入100 次删除
  1. 9 36
      BiddingKG/dl/interface/extract.py
  2. 13 0
      BiddingKG/dl/interface/getAttributes.py
  3. 143 64
      BiddingKG/dl/interface/predictor.py

+ 9 - 36
BiddingKG/dl/interface/extract.py

@@ -171,20 +171,9 @@ def predict(doc_id,text,title="",page_time="",web_source_no='',original_docchann
     payment_way_dic = predictor.getPredictor("deposit_payment_way").predict(content=list_articles[0].content)
     cost_time["deposit"] = round(time.time()-start_time,2)
 
-    # 需在getPredictor("prem")后  getAttributes.getPREMs 前
-    if len(re.findall('监理|施工|设计|勘察', title))==1 and re.search('施工|总承包|epc|EPC',title)==None:
-        keyword = re.search('监理|设计|勘察', title).group(0)
-        for list_entity in list_entitys:
-            for _entity in list_entity:
-                # print('keyword:',keyword, '_entity.notes :',_entity.notes)
-                if _entity.entity_type == "money" and _entity.notes == keyword and _entity.label==2:
-                    # if channel_dic['docchannel'] == "招标公告":
-                    if re.search('中标|成交|中选|中价|中租||结果|入围', title+list_articles[0].content[:100])==None:
-                        _entity.values[0] = 0.51
-                        _entity.set_Money(0, _entity.values)  #2021/11/18 根据公告类别把费用改为招标或中投标金额
-                    else:
-                        _entity.values[1] = 0.51
-                        _entity.set_Money(1, _entity.values)
+    # 需在getPredictor("prem").predict后  getAttributes.getPREMs 前  规则调整 监理|施工|设计|勘察类别公告的费用 为招标或中标金额
+    predictor.getPredictor("prem").correct_money_by_rule(title, list_entitys, list_articles)
+
 
     # 2021-12-29新增:提取:总价,单价
     start_time = time.time()  # 总价单价提取
@@ -205,25 +194,14 @@ def predict(doc_id,text,title="",page_time="",web_source_no='',original_docchann
     cost_time["punish"] = round(time.time()-start_time,2)
 
 
-    '''修正采购公告表格形式多种采购产品中标价格'''
-    if total_product_money>0 and len(prem[0]['prem'])==1:
-        for value in prem[0]['prem'].values():
-            for l in value['roleList']:
-                try:
-                    # if l[0] == 'win_tenderer' and float(l[2])<total_product_money:
-                    #     l[2] = total_product_money
-                    #     log('修改中标金额为所有产品总金额')
-                    if l["role_name"] == 'win_tenderer' and float(l["role_money"]['money'])<total_product_money:
-                        l["role_money"]['money'] = total_product_money
-                        log('修改中标金额为所有产品总金额')
-                except Exception as e:
-                    log('表格产品价格修正中标价格报错:%s'%e)
+    '''修正采购公告表格形式多种采购产品中标价格;中标金额小于所有产品总金额则改为总金额'''
+    getAttributes.correct_rolemoney(prem, total_product_money)
 
     '''修正channel预测类别为招标公告却有中标人及预测为中标信息却无中标关键词的类别''' # 依赖 prem
     start_time = time.time()
     # content = list_articles[0].content
     # channel_dic = predictor.getPredictor("channel").predict_rule(title, content, channel_dic, prem_dic=prem[0]['prem'])
-    channel_dic = predictor.getPredictor("channel").predict_merge(title,list_sentences[0], text, list_articles[0].bidway, prem[0], original_docchannel)
+    channel_dic, msc = predictor.getPredictor("channel").predict_merge(title,list_sentences[0], text, list_articles[0].bidway, prem[0], original_docchannel)
     cost_time["rule_channel"] = round(time.time()-start_time,2)
 
     start_time = time.time() # 产品名称及废标原因提取  #依赖 docchannel结果
@@ -235,14 +213,9 @@ def predict(doc_id,text,title="",page_time="",web_source_no='',original_docchann
     prem[0].update(getAttributes.getOtherAttributes(list_entitys[0]))
 
     '''公告无表格格式时,采购意向预测'''  #依赖 docchannel结果 依赖产品及prem
-    if channel_dic['docchannel']['docchannel']=="采购意向" and len(product_attrs[1]['demand_info']['data']) == 0:
-        product_attrs = predictor.getPredictor("product_attrs").predict_without_table(product_attrs, list_sentences,
-                                                                                      list_entitys,codeName,prem,text,page_time)
-    if len(product_attrs[1]['demand_info']['data'])>0:
-        for d in product_attrs[1]['demand_info']['data']:
-            for product in set(prem[0]['product']):
-                if product in d['project_name'] and product not in d['product']:
-                    d['product'].append(product)  #把产品在项目名称中的添加进需求要素中
+    '''把产品要素提取结果在项目名称的添加到 采购需求,预算时间,采购时间 要素中'''
+    predictor.getPredictor("product_attrs").add_product_attrs(channel_dic, product_attrs, list_sentences,list_entitys,codeName,prem,text,page_time)
+
 
     # data_res = Preprocessing.union_result(Preprocessing.union_result(codeName, prem),list_punish_dic)[0]
     # data_res = Preprocessing.union_result(Preprocessing.union_result(Preprocessing.union_result(codeName, prem),list_punish_dic), list_channel_dic)[0]

+ 13 - 0
BiddingKG/dl/interface/getAttributes.py

@@ -2888,6 +2888,19 @@ def getPREMs(list_sentences,list_entitys,list_articles,list_outlines):
         #                       "attachmentTypes":list_article.attachmentTypes, "bidway": list_article.bidway}))
     return result
 
+def correct_rolemoney(prem, total_product_money):
+    if total_product_money>0 and len(prem[0]['prem'])==1:
+        for value in prem[0]['prem'].values():
+            for l in value['roleList']:
+                try:
+                    # if l[0] == 'win_tenderer' and float(l[2])<total_product_money:
+                    #     l[2] = total_product_money
+                    #     log('修改中标金额为所有产品总金额')
+                    if l["role_name"] == 'win_tenderer' and float(l["role_money"]['money'])<total_product_money:
+                        l["role_money"]['money'] = total_product_money
+                        # log('修改中标金额为所有产品总金额')
+                except Exception as e:
+                    print('表格产品价格修正中标价格报错:%s'%e)
 
 if __name__=="__main__":
     '''

+ 143 - 64
BiddingKG/dl/interface/predictor.py

@@ -716,11 +716,26 @@ class PREMPredict():
             elif label ==0 and entity.notes in ["投资", "工程造价"]:
                 values[label] = 0.49
             entity.set_Money(label, values)
-        
+
+    def correct_money_by_rule(self, title, list_entitys, list_articles):
+        if len(re.findall('监理|施工|设计|勘察', title)) == 1 and re.search('施工|总承包|epc|EPC', title) == None:
+            keyword = re.search('监理|设计|勘察', title).group(0)
+            for list_entity in list_entitys:
+                for _entity in list_entity:
+                    # print('keyword:',keyword, '_entity.notes :',_entity.notes)
+                    if _entity.entity_type == "money" and _entity.notes == keyword and _entity.label == 2:
+                        # if channel_dic['docchannel'] == "招标公告":
+                        if re.search('中标|成交|中选|中价|中租|结果|入围', title + list_articles[0].content[:100]) == None:
+                            _entity.values[0] = 0.51
+                            _entity.set_Money(0, _entity.values)  # 2021/11/18 根据公告类别把费用改为招标或中投标金额
+                        else:
+                            _entity.values[1] = 0.51
+                            _entity.set_Money(1, _entity.values)
+
     def predict(self,list_sentences,list_entitys):
         self.predict_role(list_sentences,list_entitys)
         self.predict_money(list_sentences,list_entitys)
-        
+
         
 #联系人模型    
 class EPCPredict():
@@ -2421,6 +2436,16 @@ class ProductAttributesPredictor():
             product_attrs[1]['demand_info']['data'] = _data
         return product_attrs
 
+    def add_product_attrs(self,channel_dic, product_attrs,  list_sentences,list_entitys,codeName,prem,text,page_time):
+        if channel_dic['docchannel']['docchannel']=="采购意向" and len(product_attrs[1]['demand_info']['data']) == 0:
+            product_attrs = self.predict_without_table(product_attrs, list_sentences,
+                                                                                          list_entitys,codeName,prem,text,page_time)
+        if len(product_attrs[1]['demand_info']['data'])>0:
+            for d in product_attrs[1]['demand_info']['data']:
+                for product in set(prem[0]['product']):
+                    if product in d['project_name'] and product not in d['product']:
+                        d['product'].append(product)  #把产品在项目名称中的添加进需求要素中
+
 
 # docchannel类型提取
 class DocChannel():
@@ -2453,38 +2478,39 @@ class DocChannel():
             '土地矿产': '(土地|用地|宗地|荒地|山地|海域|矿)(出让|出租|招租|租赁|承包|流转|使用权|经营权|征收|划拨|中标|成交)|供地结果|矿业权|探矿权|采矿权|(土地|用地|宗地|地块)(使用权)?(终止|中止|网上)?(挂牌|出让|拍卖|招拍|划拨)|征收土地',
             '拍卖出让': '(拍卖|变卖|流拍|竞拍)的?(公告|公示)|拍卖|变卖|流拍|竞拍',
             '产权交易': '经营权|承包权|使用权|租赁权|股权|债权|排污权|化学需氧量|储备量|竞价销售|销售结果|出租|招租|拍租|竞租|续租|挂牌|出让',
-            '采招数据': '(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判)的?(公告|公示|中标|成交|结果|$)',  # 意向|需求|预公?告|报建|总承包|工程|施工|设计|勘察|代理|监理 |变更|答疑|澄清|中标|成交|合同|废标|流标
+            '采招数据': '(采购|招标|询价|议价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判)的?(公告|公示|中标|成交|结果|$)|工程招标', #|竞价 采招/产权都有竞价方式 # 意向|需求|预公?告|报建|总承包|工程|施工|设计|勘察|代理|监理 |变更|答疑|澄清|中标|成交|合同|废标|流标
             '新闻资讯': '(考试|面试|笔试)成绩|成绩的?(公告|公示|公布)|公开招聘|招聘(公告|简章|启事|合同制)|疫情防控\s{,5}(通知|情况|提示)'
         }
       self.life_dic = {
             '采购意向': '采购意向|招标意向|选取意向|意向公告|意向公示',
             '招标预告': '预计(采购|招标)(时间|日期)',
             '招标公告': '(采购|招标|竞选|报名)条件;报名时间;报名流程;报名方法;报名需提供的材料;参加竞价采购交易资格;(申请人|投标人|供应商|报价人|参选人)的?资格要求;获取(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|竞谈|应答)文件;(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|竞谈|应答)文件的?(获取|领取)',
-            '资审结果': '招标资审公告|评审入围公示|资审及业绩公示|资格后审情况报告|资格后审结果公告|资格后审结果公示|资格预审结果公告|资格预审结果公示|预审公示|预审结果公示',
-            '招标答疑': '现澄清为|答疑澄清公告|异议的回复|(最高(投标)?限价|控制价|拦标价)公示',
+            '资审结果': '资审及业绩公示|资格后审情况报告|资格后审结果公告|资格后审结果公示|资格预审结果公告|资格预审结果公示|预审结果公示|资格审查结果公示如下|资格预审工作已结束',
+            '招标答疑': '现澄清为|现澄清如下|澄清内容如下|第[0-9一二三四五]次澄清|答疑澄清公告|(最高(投标)?限价|控制价|拦标价)公示', #|异议的回复
             '公告变更': '原公告(主要)?(信息|内容)|变更[前后]内容|现在?(变更|更正|修改|更改)为|(变更|更正)内容为|更正理由|更正人名称|[、\s](更正信息|更正内容):',
             '候选人公示': '候选人公示|评标结果公示',
-            '中标信息': '供地结果信息|采用单源直接采购的?情况说明|现将\w{,4}(成交|中标|中选|选定结果|选取结果)\w{2,8}(进行公示|公示如下)|(中标|中选)(供应商|承包商|候选人|入围单位)如下|拟定供应商的情况|(中标(候选人|人|成交)|成交)\w{,3}(信息|情况)[::\s]',
-            '中标信息2': '(成交|中标)(日期|时间)[::\s]|成交金额:',
-            '中标信息3': '(中标|中选|成交|拟定|拟选用|最终选定的?|受让|唯一)(供应商|供货商|服务商|企业|公司|单位|候选人|人)(名称)?[::\s]|[、\s](第一名|(拟定|推荐|入围)?(供应商|供货商)|(中选|中标|供货)单位|中选人)[::\s]',
+            '中标信息': '供地结果信息|采用单源直接采购的?情况说明|现将\w{,4}(成交|中标|中选|选定结果|选取结果)\w{2,8}(进行公示|公[布]如下)|(中标|中选)(供应商|承包商|候选人|入围单位)如下|拟定供应商的情况|(中标(候选人|人|成交)|成交)\w{,3}(信息|情况)[::\s]',
+            '中标信息2': '(成交|中标)(日期|时间)[::\s]|成交金额:|中标价格:',
+            '中标信息3': '(中标|中选|成交|拟定|拟选用|最终选定的?|受让|唯一)(供应商|供货商|服务商|机构|企业|公司|单位|候选人|人)(名称)?[::\s]|[、\s](第一名|(拟定|推荐|入围)?(供应商|供货商)|(中选|中标|供货)单位|中选人)[::\s]',
             '合同公告': '合同(公告|公示)信息;合同(公告|公示)日期;合同(公告|公示)内容;合同编号;合同名称;合同签订日期;合同主体;供应商乙方',
             '废标公告': '(终止|中止|废标|流标|失败|作废|异常|撤销)(结果)?(公告|公示|招标|采购|竞价)|(谈判结果为|结果类型):废标|((本|该)项目|本标段|本次(招标)?)((采购|招标)?(失败|终止|流标|废标)|(按|做|作)(流标|废标)处理)',
+            '废标公告2': '(无效|中止|终止|废标|流标|失败|作废|异常|撤销)的?原因|本项目因故取消。'
         }
       self.title_life_dic = {
             '采购意向': '采购意向|招标意向|选取意向|意向公告|意向公示',
             '招标预告': '预公?告|预公示|报建公告|(批前|标前)公示|供应计划$|(论证|征求|征集)(供应商)?意见|意见征询|需求评审公告|需求(公告|公示|意见)',
-            '公告变更': '(变更|更正(事项)?|更改|延期|暂停)的?(公告|公示|通知)|变更$|更正$',
-            '招标答疑': '质疑|澄清|答疑(文件)?|补遗书?|(最高(投标)?限价|控制价|拦标价)公示',
+            '公告变更': '(变更|更正(事项)?|更改|延期|暂停)(招标|采购)?的?(公告|公示|通知)|变更$|更正$',
+            '招标答疑': '质疑|澄清|答疑(文件)?|补遗书?|(最高(投标)?限价|控制价|拦标价)(公示|公告|$)',
             '废标公告': '(终止|中止|废标|流标|失败|作废|异常|撤销|取消成交)(结果|竞价|项目)?的?(公告|公示|$)|(终止|中止)(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|拍卖|招租|交易|出让)',
-            '合同公告': '(合同(成交)?|履约验收|履约|验收结果)(公告|公示|信息|公式)|合同备案|合同书',  # 合同$|
-            '候选人公示': '候选人公示|评标(结果)?公示|中标前?公示|中标预公示',
-            '中标信息': '(中标|中选|中价|中租|成交|入选|确认)(候选人|人|供应商|记录|结果)?(公告|公示|结果)|(遴选|采购|招标|竞价|议价|比选|询价|评选|谈判|邀标|邀请|洽谈|约谈|评标|发包|遴选|交易)结果|开标(记录|信息|情况)|中标通知书|中标$',
+            '合同公告': '(合同(成交|变更)?|(履约|验收)(结果)?)(公告|公示|信息|公式)|合同备案|合同书',  # 合同$|
+            '候选人公示': '候选人(变更)?公示|评标(结果)?公示|中标前?公示|中标预公示',
+            '中标信息': '(中标|中选|中价|中租|成交|入选|确认)(候选人|人|供应商|记录|结果|变更)?(公告|公示|结果)|未?入围(公示|公告)|(遴选|采购|招标|竞价|议价|比选|询价|评选|谈判|邀标|邀请|洽谈|约谈|评标|发包|遴选|交易)\w{,5}结果|开标(记录|信息|情况)|中标通知书|中标$',
             # '资审结果': '(资质|资格)(预审|后审)(入围)?(公示|公告|报告)|(资质|资格)?(预审|后审)(入围)?(公示|公告|报告)|(资质|资格)(审查|预审)结果(公示)?|资审结果公示|未?入围(公示|公告)|资审及业绩公示',
-            '资审结果': '((资格|资质)(审查|预审|后审|审核|入围项?目?)|资审|入围)结果(公告|公示)?|(资质|资格)(预审|后审|入围)(入围)?(公示|公告|报告)|(资质|资格)?(预审|后审)(入围)?(公示|公告|报告)|未?入围(公示|公告)|资审及业绩公示',
-            '招标公告': '(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|拍卖|招租|交易|出让)的?(公告|公示|$)|公开(采购|招标|招租|拍卖|挂牌|出让)',
+            '资审结果': '((资格|资质)(审查|预审|后审|审核)|资审)结果(公告|公示)?|(资质|资格)(预审|后审)公示|资审及业绩公示',
+            '招标公告': '(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|拍卖|招租|交易|出让)的?(公告|公示|$)|公开(采购|招标|招租|拍卖|挂牌|出让)|(资审|预审|后审)公告',
         }
 
-      self.wrong_win = '按项目控制价下浮\d%即为成交价|不得确定为(中标|成交)|招标人按下列原则选择中标人|确定成交供应商:|评选成交供应商:|拟邀请供应商|除单一来源采购项目外|单一来源除外|(各.{,5}|尊敬的)(供应商|供货商)|竞拍起止时间:'
+      self.wrong_win = '按项目控制价下浮\d%即为成交价|不得确定为(中标|成交)|招标人按下列原则选择中标人|确定成交供应商[,\s]|评选成交供应商:|拟邀请供应商|除单一来源采购项目外|单一来源除外|(各.{,5}|尊敬的)(供应商|供货商)[:\s]|竞拍起止时间:|询价结果[\s\n::]*不公开|本项目已具备招标条件|现对该项目进行招标公告'
 
   def load_life(self,life_model):
     with tf.Graph().as_default() as graph:
@@ -2734,9 +2760,10 @@ class DocChannel():
 
       def html2text(html):
           ser = re.search('<div[^<>]*richTextFetch', html)
-          if ser:
+          if ser and len(re.sub('[^\u4e00-\u9fa5]', '', html[:ser.start()]))>500:
               html = html[:ser.start()]+'##richTextFetch##'
           text = re.sub('<[^<]*?>', '', html).replace('&nbsp;', ' ')
+          text = re.sub('http[0-9a-zA-Z-.:/]+|[0-9a-zA-Z-./@]+', '', text)
           text = re.sub('\s+', ' ', text)
           text = re.sub('[/|[()()]', '', text)
           text = cut_single_cn_space(text)
@@ -2768,34 +2795,31 @@ class DocChannel():
       def get_type(title, text):
           if re.search(self.title_type_dic['土地矿产'], title) or re.search(self.type_dic['土地矿产'],
                                                                    text):  # and re.search('(土地|用地|宗地|地块)(经营权)?(流转|承包|出租|招租|租赁|确权)', text)==None
-              if re.search(self.title_type_dic['采招数据'], title + text[:50]):
-                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text[:50]).group(0)
+              if re.search(self.title_type_dic['采招数据'], title + text.strip().split(' ')[0]):
+                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text.strip().split(' ')[0]).group(0)
               return '土地矿产', (re.search(self.title_type_dic['土地矿产'], title) or re.search(self.type_dic['土地矿产'], text)).group(0)
           elif (re.search(self.title_type_dic['拍卖出让'], title) or re.search(self.type_dic['拍卖出让'], text)):
-              if re.search(self.title_type_dic['采招数据'], title + text[:50]):
-                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text[:50]).group(0)
+              if re.search(self.title_type_dic['采招数据'], title + text.strip().split(' ')[0]):
+                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text.strip().split(' ')[0]).group(0)
               return '拍卖出让', (re.search(self.title_type_dic['拍卖出让'], title) or re.search(self.type_dic['拍卖出让'], text)).group(0)
           elif re.search(self.title_type_dic['产权交易'], title) or re.search(self.type_dic['产权交易'], text):
-              if re.search(self.title_type_dic['采招数据'], title + text[:50]):
-                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text[:50]).group(0)
+              if re.search(self.title_type_dic['采招数据'], title + text.strip().split(' ')[0]):
+                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text.strip().split(' ')[0]).group(0)
               return '产权交易', (re.search(self.title_type_dic['产权交易'], title) or re.search(self.type_dic['产权交易'], text)).group(0)
           elif re.search(self.title_type_dic['采招数据'], title) or re.search(self.type_dic['采招数据'], title + text):
               return '采招数据', (
                           re.search(self.title_type_dic['采招数据'], title) or re.search(self.type_dic['采招数据'], title + text)).group(
                   0)
           elif re.search(self.title_type_dic['新闻资讯'], title):
-              if re.search(self.title_type_dic['采招数据'], title + text[:150]):
-                  return '采招数据', re.search(self.title_type_dic['采招数据'], title + text[:150]).group(0)
+              if re.search(self.title_type_dic['采招数据'], title +text.strip().split(' ')[0]):
+                  return '采招数据', re.search(self.title_type_dic['采招数据'], title +text.strip().split(' ')[0]).group(0)
               return '新闻资讯', re.search(self.title_type_dic['新闻资讯'], title).group(0)
           else:
               return '', '没有公告类型关键词,返回空'
 
       def get_life(title, text, extract_json="", bidway="",  original_docchannel=''):
           if re.search(self.title_life_dic['采购意向'], title) and re.search(self.life_dic['采购意向'], text[:100]):
-              if re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text):
-                  return '公告变更', (re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text)).group(
-                      0)
-              elif re.search(self.title_life_dic['候选人公示'], title):
+              if re.search(self.title_life_dic['候选人公示'], title):
                   return '候选人公示', re.search(self.title_life_dic['候选人公示'], title).group(0)
               elif re.search(self.title_life_dic['中标信息'], title):
                   return '中标信息', re.search(self.title_life_dic['中标信息'], title).group(0)
@@ -2803,13 +2827,13 @@ class DocChannel():
                   return '废标公告', re.search('终止|废标|流标', title).group(0)
               elif is_single_source(bidway, title):
                   return '中标信息', 'bidway单一来源'
+              elif re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text):
+                  return '公告变更', (re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text)).group(
+                      0)
               return '采购意向', (
                           re.search(self.title_life_dic['采购意向'], title) and re.search(self.life_dic['采购意向'], text[:100])).group(0)
           elif re.search(self.title_life_dic['招标预告'], title) or re.search(self.life_dic['招标预告'], text):
-              if re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text):
-                  return '公告变更', (re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text)).group(
-                      0)
-              elif re.search(self.title_life_dic['候选人公示'], title):
+              if re.search(self.title_life_dic['候选人公示'], title):
                   return '候选人公示', re.search(self.title_life_dic['候选人公示'], title).group(0)
               elif re.search(self.title_life_dic['中标信息'], title):
                   return '中标信息', re.search(self.title_life_dic['中标信息'], title).group(0)
@@ -2817,25 +2841,15 @@ class DocChannel():
                   return '废标公告', re.search('终止|废标|流标', title).group(0)
               elif is_single_source(extract_json, title):
                   return '中标信息', 'bidway单一来源'
+              elif re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text):
+                  return '公告变更', (re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text)).group(
+                      0)
               return '招标预告', (re.search(self.title_life_dic['招标预告'], title) or re.search(self.life_dic['招标预告'], text)).group(0)
-          elif re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text):
-              if re.search(self.title_life_dic['废标公告'], title):
-                  return '废标公告', re.search(self.title_life_dic['废标公告'], title).group(0)
-              #         elif re.search('(中标|成交)结果', title[-8:]):
-              #             return '中标信息', re.search('(中标|成交)结果', title[-8:]).group(0)       
-              return '公告变更', (re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text)).group(0)
-          elif re.search(self.title_life_dic['招标答疑'], title) or re.search(self.life_dic['招标答疑'], text) or len(
-                  re.findall('(答:|回复:)', text)) >= 2:  # or re.search(self.title_life_dic['招标答疑'], text[:150])
-              if re.search(self.title_life_dic['废标公告'], title):
-                  return '废标公告', re.search(self.title_life_dic['废标公告'], title).group(0)
-              elif re.search('(中标|成交)结果', title[-8:]):
-                  return '中标信息', re.search('(中标|成交)结果', title[-8:]).group(0)
-              return '招标答疑', (
-                          re.search(self.title_life_dic['招标答疑'], title) or re.search(self.life_dic['招标答疑'], text) or re.search(
-                      '(答:|回复:)', text)).group(0)
-          elif re.search(self.title_life_dic['废标公告'], title+ text[:150]) or re.search(self.life_dic['废标公告'], text[:150]):
+          elif re.search(self.title_life_dic['废标公告'], title+text.strip().split(' ')[0]) or re.search(self.life_dic['废标公告'], text[:150]):
               return '废标公告', (
-                          re.search(self.title_life_dic['废标公告'], title+ text[:150]) or re.search(self.life_dic['废标公告'], text[:150])).group(0)
+                          re.search(self.title_life_dic['废标公告'], title+text.strip().split(' ')[0]) or re.search(self.life_dic['废标公告'], text[:150])).group(0)
+          elif re.search(self.life_dic['废标公告2'], text[:]) and not is_contain_winner(extract_json):
+              return '废标公告', re.search(self.life_dic['废标公告2'], text[:]).group(0)
           elif re.search(self.title_life_dic['候选人公示'], title) or re.search(self.life_dic['候选人公示'], text[:150]):
               if re.search('候选人|公示期?(已?满|已经?结束)|中标(结果|公告)', text) == None:
                   return '中标信息', '候选人公示排除,修改为中标信息'
@@ -2859,14 +2873,14 @@ class DocChannel():
           elif is_single_source(extract_json, title):
               return '中标信息', '单一来源采购'
           elif re.search(self.title_life_dic['中标信息'], title):
-              if re.search(self.title_life_dic['资审结果'], title+text[:150]):
-                  return '资审结果', re.search(self.title_life_dic['资审结果'], title+text[:150]).group(0)
+              if re.search(self.title_life_dic['资审结果'], title+text.strip().split(' ')[0]):
+                  return '资审结果', re.search(self.title_life_dic['资审结果'], title+text.strip().split(' ')[0]).group(0)
               return '中标信息', re.search(self.title_life_dic['中标信息'], title).group(0)
           elif re.search(self.title_life_dic['中标信息'], text[:100]) or re.search(self.life_dic['中标信息'], text[:]):
-              if re.search(self.title_life_dic['资审结果'], title+text[:150]):
-                  return '资审结果', re.search(self.title_life_dic['资审结果'], title+text[:150]).group(0)
-              # if re.search(self.wrong_win, text):
-              #     return '招标公告', re.search(self.wrong_win, text).group(0)
+              if re.search(self.title_life_dic['资审结果'], title+text.strip().split(' ')[0]):
+                  return '资审结果', re.search(self.title_life_dic['资审结果'], title+text.strip().split(' ')[0]).group(0)
+              if re.search(self.wrong_win, text):
+                  return '招标公告', re.search(self.wrong_win, text).group(0)
               return '中标信息', (
                           re.search(self.title_life_dic['中标信息'], text[:100]) or re.search(self.life_dic['中标信息'], text[:])).group(
                   0)
@@ -2892,8 +2906,29 @@ class DocChannel():
               elif re.search('##richTextFetch##', text):
                   return '', '提取到中标人但包含附件返回空'
               return '中标信息', '提取到中标人'
-          elif re.search(self.title_life_dic['资审结果'], title+text[:150]) or re.search(self.life_dic['资审结果'], text[:]):
-              return '资审结果', (re.search(self.title_life_dic['资审结果'], title+text[:150]) or re.search(self.life_dic['资审结果'], text[:])).group(0)
+          elif re.search(self.title_life_dic['资审结果'], title+text.strip().split(' ')[0]) or re.search(self.life_dic['资审结果'], text[:150]):
+              return '资审结果', (re.search(self.title_life_dic['资审结果'], title+text.strip().split(' ')[0]) or re.search(self.life_dic['资审结果'], text[:150])).group(0)
+          elif re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text):
+              if re.search(self.title_life_dic['废标公告'], title):
+                  return '废标公告', re.search(self.title_life_dic['废标公告'], title).group(0)
+              elif re.search(self.title_life_dic['候选人公示'], title):
+                  return '候选人公示', re.search(self.title_life_dic['候选人公示'], title).group(0)
+              elif re.search(self.title_life_dic['中标信息'], title):
+                  return '中标信息', re.search(self.title_life_dic['中标信息'], title).group(0)
+              elif is_single_source(extract_json, title):
+                  return '中标信息', 'bidway单一来源'
+              #         elif re.search('(中标|成交)结果', title[-8:]):
+              #             return '中标信息', re.search('(中标|成交)结果', title[-8:]).group(0)
+              return '公告变更', (re.search(self.title_life_dic['公告变更'], title) or re.search(self.life_dic['公告变更'], text)).group(0)
+          elif re.search(self.title_life_dic['招标答疑'], title) or re.search(self.life_dic['招标答疑'], text[:200]) or len(
+                  re.findall('(答:|回复:)', text)) >= 2:  # or re.search(self.title_life_dic['招标答疑'], text[:150])
+              if re.search(self.title_life_dic['废标公告'], title):
+                  return '废标公告', re.search(self.title_life_dic['废标公告'], title).group(0)
+              elif re.search('(中标|成交)结果', title[-8:]):
+                  return '中标信息', re.search('(中标|成交)结果', title[-8:]).group(0)
+              return '招标答疑', (
+                          re.search(self.title_life_dic['招标答疑'], title) or re.search(self.life_dic['招标答疑'], text[:200]) or re.search(
+                      '(答:|回复:)', text)).group(0)
           elif re.search(self.title_life_dic['招标公告'], title) or re.search(self.life_dic['招标公告'].replace(';', '|'), text[:]):
               if re.search('意向|预告|变更|更正|中标|中选|成交|答疑|废标|流标|终止', title):
                   return '', '招标正则召回标题有其他类别关键词,返回空'
@@ -2913,10 +2948,33 @@ class DocChannel():
           112: '全国工程人员',
           113: '业主采购'
       }
+
+      origin_dic = {51: '公告变更',
+       52: '招标公告',
+       101: '中标信息',
+       102: '招标预告',
+       103: '招标答疑',
+       104: '招标文件',
+       105: '资审结果',
+       106: '法律法规',
+       107: '新闻资讯',
+       108: '拟建项目',
+       109: '展会推广',
+       110: '企业名录',
+       111: '企业资质',
+       112: '全国工程',
+       113: '业主采购',
+       114: '采购意向',
+       115: '拍卖出让',
+       116: '土地矿产',
+       117: '产权交易',
+       118: '废标公告',
+       119: '候选人公示',
+       120: '合同公告'}
       if original_docchannel in not_extract_dic:
-          return {'docchannel': {'docchannel': '', 'doctype': not_extract_dic[original_docchannel]}}
-      if web_source_no in ['02104-7', '04733']: # 这些数据源无法识别
-          return {'docchannel': {'docchannel': '', 'doctype': '采招数据'}}
+          return {'docchannel': {'docchannel': '', 'doctype': not_extract_dic[original_docchannel], 'life_docchannel': origin_dic.get(original_docchannel, '原始类别')}}
+      if web_source_no in ['02104-7', '04733', 'DX007628-6']: # 这些数据源无法识别
+          return {'docchannel': {'docchannel': '', 'doctype': '采招数据', 'life_docchannel': origin_dic.get(original_docchannel, '原始类别')}}
 
       title = re.sub('[^\u4e00-\u9fa5]', '', title)
       if len(title) > 50:
@@ -2932,7 +2990,9 @@ class DocChannel():
           result['docchannel']['doctype'] = doc_type
       if doc_life in self.title_life_dic:
           result['docchannel']['docchannel'] = doc_life
-
+      # print('channel正则预测结果:', result)
+      msc = '正则结果:类型:%s, 关键词:%s, 周期:%s, 关键词:%s'%(doc_type, type_kw,doc_life, life_kw)+'\n'+'模型结果:'
+      # print('类型:%s, 关键词:%s, 周期:%s, 关键词:%s'%(doc_type, type_kw,doc_life, life_kw))
       if doc_type=="" or doc_life=="":
           list_sentence = sorted(list_sentence, key=lambda x:x.sentence_index)
           token_l = [it.tokens for it in list_sentence]
@@ -2958,6 +3018,7 @@ class DocChannel():
               id = np.argmax(pred, axis=1)[0]
               prob = pred[0][id]
               result['docchannel']['doctype'] = self.id2type[id]
+              msc += self.id2type[id] + ';'
               # print('公告类别:', self.id2type[id], '概率:',prob)
               # if id == 0:
           if doc_life=="" and result['docchannel']['doctype'] not in ['', '新闻资讯']:
@@ -2971,9 +3032,20 @@ class DocChannel():
                                                 self.lift_prob: 1}
                                             )
                   id = np.argmax(pred, axis=1)[0]
+                  msc += self.id2life[id] + ';\n'
                   prob = pred[0][id]
-                  if self.id2life[id] == '中标信息' and original_docchannel in [52, '52', '招标公告'] and not is_contain_winner(prem_json):
+                  if self.id2life[id] == '中标信息' and original_docchannel in [51,52,102,103,114] and not is_contain_winner(prem_json):
+                      result['docchannel']['docchannel'] = origin_dic.get(original_docchannel, '原始类别')
+                      msc += '模型预测为中标而无中标人且原始为非中标,返回原始类别;'
+                  elif self.id2life[id] == '采购意向' and re.search('意向品牌|意向单位', text):
                       result['docchannel']['docchannel'] = '招标公告'
+                      msc += '模型为意向,正文有意向品牌等词改为招标公告;'
+                  elif self.id2life[id] == '招标答疑' and re.search('质疑|澄清|答疑(文件)?|补遗书?|(投标)?限价|控制价|拦标价',  title+text[:500])==None:
+                      result['docchannel']['docchannel'] = origin_dic.get(original_docchannel, '原始类别')
+                      msc += '模型为答疑,正文无答疑关键词改为原始类别;'
+                  elif prob<0.5:
+                      result['docchannel']['docchannel'] = origin_dic.get(original_docchannel, '原始类别')
+                      msc += '模型概率小于0.5,返回原始类别;'
                   else:
                       result['docchannel']['docchannel'] = self.id2life[id]
                       # print('生命周期:',self.id2life[id], '概率:',prob)
@@ -2986,7 +3058,14 @@ class DocChannel():
                               # return [{'docchannel': '候选人公示'}]
       # print('公告类型:%s, 生命周期:%s, 关键词:%s '%(doc_type, doc_life, life_kw))
       # print('result: ', result)
-      return result
+      if result['docchannel']['docchannel'] == '废标公告' and is_contain_winner(prem_json) and re.search(self.title_life_dic['废标公告'], title)==None:
+          result['docchannel']['docchannel'] = '中标信息'
+          msc += '最终规则修改:预测为废标却有中标人且标题无废标关键词改为中标信息;'
+      if result['docchannel']['docchannel'] != '': # 预测到生命周期的复制到life_docchannel,否则用数据源结果
+          result['docchannel']['life_docchannel'] = result['docchannel']['docchannel']
+      else:
+          result['docchannel']['life_docchannel'] = origin_dic.get(original_docchannel, '原始类别')
+      return result, msc
 
 # 保证金支付方式提取
 class DepositPaymentWay():