Bläddra i källkod

Merge branch 'package'

lsm 2 år sedan
förälder
incheckning
fb929e45a6

+ 5 - 2
BiddingKG/dl/interface/Preprocessing.py

@@ -1775,6 +1775,9 @@ def special_treatment(sourceContent, web_source_no):
         elif web_source_no=='DX000105-2':
         elif web_source_no=='DX000105-2':
             if re.search("成交公示", sourceContent) and re.search(',投标人:', sourceContent) and re.search(',成交人:', sourceContent)==None:
             if re.search("成交公示", sourceContent) and re.search(',投标人:', sourceContent) and re.search(',成交人:', sourceContent)==None:
                 sourceContent = sourceContent.replace(',投标人:', ',成交人:')
                 sourceContent = sourceContent.replace(',投标人:', ',成交人:')
+        elif web_source_no in ['03795-1', '03795-2']:
+            if re.search('中标单位如下', sourceContent) and re.search(',投标人:', sourceContent) and re.search(',中标人:', sourceContent)==None:
+                sourceContent = sourceContent.replace(',投标人:', ',中标人:')
         elif web_source_no in ['04080-3', '04080-4']:
         elif web_source_no in ['04080-3', '04080-4']:
             ser = re.search('合同金额:([0-9,]+.[0-9]{3,})(.{,4})', sourceContent)
             ser = re.search('合同金额:([0-9,]+.[0-9]{3,})(.{,4})', sourceContent)
             if ser and '万' not in ser.group(2):
             if ser and '万' not in ser.group(2):
@@ -2087,7 +2090,7 @@ def get_preprocessed_article(articles,cost_time = dict(),useselffool=True):
         article_processed = segment(article_processed)
         article_processed = segment(article_processed)
 
 
         article_processed = article_processed.replace('(', '(').replace(')', ')')  #2022/8/10 统一为中文括号
         article_processed = article_processed.replace('(', '(').replace(')', ')')  #2022/8/10 统一为中文括号
-        article_processed = article_processed.replace('.','.') # 2021/12/01 修正OCR识别PDF小数点错误问题
+        article_processed = article_processed.replace('.','.').replace('-', '-') # 2021/12/01 修正OCR识别PDF小数点错误问题
         article_processed = article_processed.replace('报价限价', '招标限价') #2021/12/17 由于报价限价预测为中投标金额所以修改
         article_processed = article_processed.replace('报价限价', '招标限价') #2021/12/17 由于报价限价预测为中投标金额所以修改
         article_processed = article_processed.replace('成交工程价款', '成交工程价')  # 2021/12/21 修正为中标价
         article_processed = article_processed.replace('成交工程价款', '成交工程价')  # 2021/12/21 修正为中标价
         article_processed = re.sub('任务(?=编号[::])', '项目',article_processed)  # 2022/08/10 修正为项目编号
         article_processed = re.sub('任务(?=编号[::])', '项目',article_processed)  # 2022/08/10 修正为项目编号
@@ -2111,7 +2114,7 @@ def get_preprocessed_article(articles,cost_time = dict(),useselffool=True):
             article_processed_list[1] = attachment_text
             article_processed_list[1] = attachment_text
             article_processed = "##attachment##".join(article_processed_list)
             article_processed = "##attachment##".join(article_processed_list)
         '''特别数据源对 预处理后文本 做特别修改'''
         '''特别数据源对 预处理后文本 做特别修改'''
-        if web_source_no in ['03786-10', '00076-4', 'DX000105-2', '04080-3', '04080-4', '03761-3', '00695-7',"13740-2", '00811-8']:
+        if web_source_no in ['03786-10', '00076-4', 'DX000105-2', '04080-3', '04080-4', '03761-3', '00695-7',"13740-2", '00811-8', '03795-1', '03795-2']:
             article_processed = special_treatment(article_processed, web_source_no)
             article_processed = special_treatment(article_processed, web_source_no)
 
 
         # 提取bidway
         # 提取bidway

+ 288 - 2
BiddingKG/dl/interface/getAttributes.py

@@ -556,7 +556,7 @@ def getPackageScopePattern():
     return pattern
     return pattern
         
         
 pattern_packageScope = getPackageScopePattern()   
 pattern_packageScope = getPackageScopePattern()   
-def getPackagesFromArticle(list_sentence,list_entity):
+def getPackagesFromArticle_backup(list_sentence,list_entity):
     '''
     '''
     @param:
     @param:
         list_sentence:文章的句子list
         list_sentence:文章的句子list
@@ -784,6 +784,291 @@ def getPackagesFromArticle(list_sentence,list_entity):
                 PackageList.append(copy_pack)
                 PackageList.append(copy_pack)
     return PackageList,PackageSet,dict_packageCode
     return PackageList,PackageSet,dict_packageCode
 
 
+def getPackagesFromArticle(list_sentence, list_entity):
+    '''
+    @param:
+        list_sentence:文章的句子list
+    @summary: 将包的信息插入list_entity中
+    @return: type:list if [包号,句子index,词偏移,标段号] meaning:文章的包/标段信息
+    '''
+
+    if len(list_sentence) == 0:
+        return None
+    list_sentence.sort(key=lambda x: x.sentence_index)
+
+    PackageList = []
+    PackageList_scope = []
+    PackageSet = set()
+    dict_packageCode = dict()
+
+    package_number_pattern =  re.compile(
+    '((施工|监理|监测|勘察|设计)(标段)?[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦa-zA-Z]{,4}(标段?|包))|(([a-zA-Z]包[:)]?)?第?[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦa-zA-Z]{1,4}标段?)|((标[段号的包项]|([标分子]|合同|项目|采购|()包|包[组件号])[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦA-Za-z]{1,4})|(([,;。、:(]|第)[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}分?包)|([a-zA-Z][0-9]{,3}分?[包标])|.{,1}((包组|包件|包号|分?包|标[段号的包]|子项目)编?号?[::]?[a-zA-Z0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ-]+)|[,;。、:(]包[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}[^\w]')  # 标号
+    other_package_pattern = re.compile(
+        '((项目|物资|设备|场次|标段|标的|产品)(名称)?)[::]([^,。]{2,50}?)[,。]')  # # 2020/11/23 大网站规则 调整  package_N_name_pattern, package_N_name_pattern 中的项目 改为 子项目
+    win_tenderer_pattern = re.compile('(中标候?选?人|供应商)(名称)?[::](.{2,25})[,。]')  # 2020/11/23 大网站规则 调整
+    model_pattern = re.compile('(型号|序号)[::]([^,。]{2,20})[,。]')  # 2020/11/23 大网站规则 调整
+    number_pattern = re.compile("[0-9A-Za-z一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}")
+
+    package_code_pattern = re.compile("(?:编号[::]?\s*)([-\dA-Za-z\(\)]+)")
+    # 纯数字类型的包号统一,例如:'01','1'
+    re_digital = re.compile("^\d+$")
+
+    def changeIndexFromWordToWords(tokens, word_index):
+        '''
+        @summary:转换某个字的字偏移为词偏移
+        '''
+        before_index = 0
+        after_index = 0
+        for i in range(len(tokens)):
+            after_index = after_index + len(tokens[i])
+            if before_index <= word_index and after_index >= word_index:
+                return i
+            before_index = after_index
+
+    package_names = []
+
+    def extractPackageCode(tokens, word_index, size=20, pattern=package_code_pattern):
+        '''
+        @summary:抽取包附近的标段号
+        @param:
+            tokens:包所在句子的分词
+            word_index:包所在字偏移
+            size:左右各取多少个词
+            pattern:提取标段号的正则
+        @return: type:string,meaning:标段号
+        '''
+        index = changeIndexFromWordToWords(tokens, word_index)
+        if index < size:
+            begin = index
+        else:
+            begin = index - size
+        if index + size > len(tokens):
+            end = len(tokens)
+        else:
+            end = index + size
+        # 拿到左右两边的词语组成短语
+        text = "".join(tokens[begin:end])
+        # 在短语中的字偏移
+        new_word_index = word_index - len("".join(tokens[:begin]))
+        min_distance = len(text)
+        packageCode = None
+        for the_iter in re.finditer(pattern, text):
+            # 算出最小距离
+            distance = min([abs(new_word_index - the_iter.span()[0]), abs(new_word_index - the_iter.span()[1])])
+            if distance < min_distance:
+                min_distance = distance
+                packageCode = the_iter.group(1)
+        return packageCode
+
+    def uniform_num(num):
+        d1 = {'一': '1', '二': '2', '三': '3', '四': '4', '五': '5', '六': '6', '七': '7', '八': '8', '九': '9', '十': '10'}
+        # d2 = {'A': '1', 'B': '2', 'C': '3', 'D': '4', 'E': '5', 'F': '6', 'G': '7', 'H': '8', 'I': '9', 'J': '10'}
+        d3 = {'Ⅰ': '1', 'Ⅱ': '2', 'Ⅲ': '3', 'Ⅳ': '4', 'Ⅴ': '5', 'Ⅵ': '6', 'Ⅶ': '7'}
+        if num.isdigit():
+            if re.search('^0[\d]$', num):
+                num = num[1:]
+            return num
+        elif re.search('^[一二三四五六七八九十]+$', num):
+            _digit = re.search('^[一二三四五六七八九十]+$', num).group(0)
+            if len(_digit) == 1:
+                num = d1[_digit]
+            elif len(_digit) == 2 and _digit[0] == '十':
+                num = '1'+ d1[_digit[1]]
+            elif len(_digit) == 3 and _digit[1] == '十':
+                num = d1[_digit[0]] + d1[_digit[2]]
+        elif re.search('[ⅠⅡⅢⅣⅤⅥⅦ]', num):
+            num = re.search('[ⅠⅡⅢⅣⅤⅥⅦ]', num).group(0)
+            num = d3[num]
+        return num
+
+    def uniform_package_name(package_name):
+        package_name = re.sub('pdf|doc|docs|xlsx', '', package_name)
+        kw = re.search('(施工|监理|监测|勘察|设计)', package_name)
+        name = ""
+        if kw:
+            name += kw.group(0)
+        if re.search('([a-zA-Z]包[:)]?第?[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}标段?)', package_name): # 处理类似 A包2标段
+            _char = re.search('[a-zA-Z]', package_name).group(0)
+            _digit = re.search('[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}', package_name).group(0)
+            _digit = uniform_num(_digit)
+            name += _char + _digit
+        elif re.search('[a-zA-Z0-9-]{5,}', package_name):   # 五个字符以上编号
+            _digit = re.search('[a-zA-Z0-9-]{5,}', package_name).group(0).upper()
+            name += _digit
+        elif re.search('[a-zA-Z]{1,4}[0-9]{,3}', package_name):  # 英文的统一为大写
+            _digit = re.search('[a-zA-Z]{1,4}[0-9]{,3}', package_name).group(0).upper()
+            name += _digit
+        elif re.search('[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}', package_name):  # 数字的统一的阿拉伯数字
+            _digit = re.search('[0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}', package_name).group(0)
+            _digit = uniform_num(_digit)
+            name += _digit
+        if name == "":
+            return package_name
+        else:
+            # print('原始包号:%s, 处理后:%s'%(package_name, name))
+            return name
+
+    def get_package():
+        PackageList_scope = []
+        for i in range(len(list_sentence)):
+            PackageList_item = []
+            PackageList_item_scope = []
+            content = list_sentence[i].sentence_text
+            tokens = list_sentence[i].tokens
+            _names = []
+            for iter in re.finditer(package_number_pattern, content):
+                if re.match('\d', iter.group(0)) and iter.end() < len(content) and content[
+                    iter.end()].isdigit():  # 排除2.10标段3 这种情况
+                    continue
+                if re.search('承包|XX|xx', iter.group(0)) or re.search('[a-zA-Z0-9一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ-]{6,}', iter.group(0)):
+                    continue
+                temp_package_number = uniform_package_name(iter.group(0))
+                PackageList_item.append({"name": temp_package_number, "sentence_index": list_sentence[i].sentence_index,
+                                         "offsetWords_begin": changeIndexFromWordToWords(tokens, iter.span()[0]),
+                                         "offsetWord_begin": iter.span()[0], "offsetWord_end": iter.span()[1]})
+                # PackageList_item.append([temp_package_number,i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
+                code = extractPackageCode(tokens, iter.span()[0])
+                if code is not None:
+                    dict_packageCode[temp_package_number] = code
+                PackageSet.add(temp_package_number)
+
+            # 识别packageScope
+            for iter in re.finditer(pattern_packageScope, content):
+                PackageList_item_scope.append({"name": "", "sentence_index": list_sentence[i].sentence_index,
+                                               "offsetWords_begin": changeIndexFromWordToWords(tokens, iter.span()[0]),
+                                               "offsetWord_begin": iter.span()[0], "offsetWord_end": iter.span()[1]})
+                # PackageList_item_scope.append(["",i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
+            PackageList_item_scope = PackageList_item + PackageList_item_scope
+            PackageList_item_scope.sort(key=lambda x: x["offsetWord_begin"])
+            PackageList_scope = PackageList_scope + PackageList_item_scope
+            PackageList_item.sort(key=lambda x: x["sentence_index"])
+        return PackageList_scope
+
+    def get_win_project():
+        '''获取多个项目多个中标人的项目'''
+        PackageList_scope = []
+        # 2020/11/23 大网站规则 调整
+        if len(PackageSet) == 0 and len(
+                set([it.entity_text for it in list_entity if
+                     it.entity_type in ['org', 'company'] and it.label == 2])) > 1:
+            for i in range(len(list_sentence)):
+                PackageList_item = []
+                PackageList_item_scope = []
+                content = list_sentence[i].sentence_text
+                tokens = list_sentence[i].tokens
+                names = re.findall(other_package_pattern, content)
+                N_names = re.findall(win_tenderer_pattern, content)
+                if len(names) != 1 or len(N_names) != 1:
+                    continue
+                for iter in re.finditer(other_package_pattern, content):
+                    temp_package_number = iter.group(4)
+                    xinghao = re.search(model_pattern, content)
+                    if xinghao:
+                        temp_package_number = temp_package_number + '+' + xinghao.group(2)
+                    # print('新正则采购包名补充',temp_package_number)
+                    if re.search(re_digital, temp_package_number):
+                        temp_package_number = str(int(temp_package_number))
+                    PackageList_item.append(
+                        {"name": temp_package_number, "sentence_index": list_sentence[i].sentence_index,
+                         "offsetWords_begin": changeIndexFromWordToWords(tokens, iter.span()[0]),
+                         "offsetWord_begin": iter.span()[0], "offsetWord_end": iter.span()[1]})
+                    # PackageList_item.append([temp_package_number,i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
+                    code = extractPackageCode(tokens, iter.span()[0])
+                    if code is not None:
+                        dict_packageCode[temp_package_number] = code
+                    PackageSet.add(temp_package_number)
+                # 识别packageScope
+                for iter in re.finditer(pattern_packageScope, content):
+                    PackageList_item_scope.append({"name": "", "sentence_index": list_sentence[i].sentence_index,
+                                                   "offsetWords_begin": changeIndexFromWordToWords(tokens,
+                                                                                                   iter.span()[0]),
+                                                   "offsetWord_begin": iter.span()[0],
+                                                   "offsetWord_end": iter.span()[1]})
+                    # PackageList_item_scope.append(["",i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
+                PackageList_item_scope = PackageList_item + PackageList_item_scope
+                PackageList_item_scope.sort(key=lambda x: x["offsetWord_begin"])
+                PackageList_scope = PackageList_scope + PackageList_item_scope
+                PackageList_item.sort(key=lambda x: x["sentence_index"])
+        return PackageList_scope
+
+    def get_package_scope(PackageList_scope):
+        PackageList = []
+        pattern_punctuation = "[::()\(\),,。;;]"
+        # print("===packageList_scope",PackageList_scope)
+        for i in range(len(list_sentence)):
+            for j in range(len(PackageList_scope)):
+                if i == PackageList_scope[j]["sentence_index"] and PackageList_scope[j]["name"] != "":
+                    _flag = False
+                    left_str = list_sentence[i].sentence_text[
+                               PackageList_scope[j]["offsetWord_begin"] - 30:PackageList_scope[j][
+                                                                                 "offsetWord_begin"] + 1]
+                    right_str = list_sentence[i].sentence_text[
+                                PackageList_scope[j]["offsetWord_begin"]:PackageList_scope[j]["offsetWord_begin"] + 30]
+                    _left_find = re.findall(pattern_punctuation, left_str)
+                    _right_find = re.findall(pattern_punctuation, right_str)
+                    # print(left_str)
+                    if re.search("同", left_str[-1:]) is not None and PackageList_scope[j]["name"] == "一":
+                        continue
+                    if re.search("划分", right_str[:10]) is not None:
+                        continue
+                    if len(_left_find) > 0 and _left_find[-1] in [":", ":"]:
+                        _flag = True
+                    if len(_right_find) > 0 and _right_find[0] in [":", ":"]:
+                        _flag = True
+                    if _flag:
+                        scope_begin = [PackageList_scope[j]["sentence_index"],
+                                       PackageList_scope[j]["offsetWords_begin"]]
+                    else:
+                        if j == 0:
+                            scope_begin = [0, 0]
+                        else:
+                            scope_begin = [PackageList_scope[j - 1]["sentence_index"],
+                                           PackageList_scope[j - 1]["offsetWords_begin"]]
+                    if j == len(PackageList_scope) - 1:
+                        scope_end = [list_sentence[-1].sentence_index,
+                                     changeIndexFromWordToWords(list_sentence[-1].tokens,
+                                                                len(list_sentence[
+                                                                        -1].sentence_text))]
+                    else:
+                        scope_end = [PackageList_scope[j + 1]["sentence_index"],
+                                     PackageList_scope[j + 1]["offsetWords_begin"]]
+                    if PackageList_scope[j - 1]["sentence_index"] == PackageList_scope[j]["sentence_index"] and \
+                            PackageList_scope[j - 1]["offsetWord_begin"] <= PackageList_scope[j]["offsetWord_begin"] and \
+                            PackageList_scope[j - 1]["offsetWord_end"] >= PackageList_scope[j]["offsetWord_end"]:
+                        continue
+
+                    # add package to entity
+                    _pack_entity = Entity(doc_id=list_sentence[0].doc_id, entity_id="%s_%s_%s_%s" % (
+                        list_sentence[0].doc_id, i, PackageList_scope[j]["offsetWord_begin"],
+                        PackageList_scope[j]["offsetWord_begin"]), entity_text=PackageList_scope[j]["name"],
+                                          entity_type="package", sentence_index=PackageList_scope[j]["sentence_index"],
+                                          begin_index=changeIndexFromWordToWords(list_sentence[i].tokens,
+                                                                                 PackageList_scope[j][
+                                                                                     "offsetWord_begin"]),
+                                          end_index=changeIndexFromWordToWords(list_sentence[i].tokens,
+                                                                               PackageList_scope[j]["offsetWord_end"]),
+                                          wordOffset_begin=PackageList_scope[j]["offsetWord_begin"],
+                                          wordOffset_end=PackageList_scope[j]["offsetWord_end"],
+                                          in_attachment=list_sentence[i].in_attachment)
+                    list_entity.append(_pack_entity)
+                    copy_pack = copy.copy(PackageList_scope[j])
+                    copy_pack["scope"] = [scope_begin, scope_end]
+                    copy_pack["hit"] = set()
+                    copy_pack["pointer"] = _pack_entity
+                    PackageList.append(copy_pack)
+        return PackageList
+
+    PackageList_scope = get_package()
+    if len(PackageList_scope) > 0: # 找到标段
+        PackageList = get_package_scope(PackageList_scope)
+    else:
+        PackageList_scope = get_win_project()
+        if len(PackageList_scope) > 1: # 同时包含多标段及多中标人的
+            PackageList = get_package_scope(PackageList_scope)
+
+    return PackageList, PackageSet, dict_packageCode
+
+
 # km配对方法
 # km配对方法
 def dispatch(match_list):
 def dispatch(match_list):
     main_roles = list(set([match.main_role for match in match_list]))
     main_roles = list(set([match.main_role for match in match_list]))
@@ -3047,7 +3332,8 @@ def limit_maximum_amount(prem, industry):
         '工程评价服务': 100000000,
         '工程评价服务': 100000000,
         '其他工程服务': 100000000,
         '其他工程服务': 100000000,
         '工程监理服务': 100000000,
         '工程监理服务': 100000000,
-        '工程造价服务': 100000000
+        '工程造价服务': 100000000,
+        '会计、审计及税务服务': 100000000,
     }
     }
     if indu in indu_amount:
     if indu in indu_amount:
         maximum_amount = indu_amount[indu]
         maximum_amount = indu_amount[indu]

+ 3 - 3
BiddingKG/dl/interface/predictor.py

@@ -2962,15 +2962,15 @@ class DocChannel():
           '资审结果': '资审及业绩公示|资审结果及业绩|资格后审情况报告|资格(后审|预审|审查)结果(公告|公示)|(预审|审查)工作已经?结束|未通过原因', #|资格
           '资审结果': '资审及业绩公示|资审结果及业绩|资格后审情况报告|资格(后审|预审|审查)结果(公告|公示)|(预审|审查)工作已经?结束|未通过原因', #|资格
           '招标答疑': '现澄清(为|如下)|答疑补遗|澄清内容如下|第[0-9一二三四五]次澄清|答疑澄清|(最高(投标)?限价|控制价|拦标价)公示',  # |异议的回复
           '招标答疑': '现澄清(为|如下)|答疑补遗|澄清内容如下|第[0-9一二三四五]次澄清|答疑澄清|(最高(投标)?限价|控制价|拦标价)公示',  # |异议的回复
           '公告变更': '第[\d一二]次变更|(更正|变更)(公告|公示|信息|内容|事项|原因|理由|日期|时间|如下)|原公告((主要)?(信息|内容)|发布时间)|(变更|更正)[前后]内容|现?在?(变更|更正|修改|更改)(内容)?为|(公告|如下|信息|内容|事项|结果|文件|发布|时间|日期)(更正|变更)',
           '公告变更': '第[\d一二]次变更|(更正|变更)(公告|公示|信息|内容|事项|原因|理由|日期|时间|如下)|原公告((主要)?(信息|内容)|发布时间)|(变更|更正)[前后]内容|现?在?(变更|更正|修改|更改)(内容)?为|(公告|如下|信息|内容|事项|结果|文件|发布|时间|日期)(更正|变更)',
-          '候选人公示': '候选人公示|评标结果公示',
+          '候选人公示': '候选人公示|评标结果公示|中标候选人名单公示',
           '中标信息': '供地结果信息|采用单源直接采购的?情况说明|[特现]?将\w{,4}(成交|中标|中选|选定结果|选取结果|入围结果)\w{,4}(进行公示|公[示布]如下)|(中标|中选)(供应商|承包商|候选人|入围单位)如下|拟定供应商的情况|((中标|中选)(候选人|人|成交)|成交)\w{,3}(信息|情况)[::\s]',
           '中标信息': '供地结果信息|采用单源直接采购的?情况说明|[特现]?将\w{,4}(成交|中标|中选|选定结果|选取结果|入围结果)\w{,4}(进行公示|公[示布]如下)|(中标|中选)(供应商|承包商|候选人|入围单位)如下|拟定供应商的情况|((中标|中选)(候选人|人|成交)|成交)\w{,3}(信息|情况)[::\s]',
           '中标信息2': '\s(成交|中标|中选)(信息|日期|时间|总?金额|价格)[::\s]|(采购|招标|成交|中标|中选|评标)结果|单一来源采购原因|拟采取单一来源方式采购|单一来源采购公示',
           '中标信息2': '\s(成交|中标|中选)(信息|日期|时间|总?金额|价格)[::\s]|(采购|招标|成交|中标|中选|评标)结果|单一来源采购原因|拟采取单一来源方式采购|单一来源采购公示',
           '中标信息3': '(中标|中选|成交|拟定|拟选用|最终选定的?|受让|唯一)(供应商|供货商|服务商|机构|企业|公司|单位|候选人|人)(名称)?[::\s]|[、\s](第一名|(拟定|推荐|入围)?(供应商|供货商)|(中选|中标|供货)单位|中选人)[::\s]',
           '中标信息3': '(中标|中选|成交|拟定|拟选用|最终选定的?|受让|唯一)(供应商|供货商|服务商|机构|企业|公司|单位|候选人|人)(名称)?[::\s]|[、\s](第一名|(拟定|推荐|入围)?(供应商|供货商)|(中选|中标|供货)单位|中选人)[::\s]',
-          '中标信息neg': '按项目控制价下浮\d%即为成交价|成交原则|不得确定为(中标|成交)|招标人按下列原则选择中标人|评选成交供应商:|拟邀请供应商|除单一来源采购项目外|单一来源除外|(各.{,5}|尊敬的)(供应商|供货商)[:\s]|竞拍起止时间:|询价结果[\s\n::]*不公开|本项目已具备招标条件|现对该项目进行招标公告|发布\w{2}结果后\d天内送达|本次\w{2}结果不对外公示',
+          '中标信息neg': '按项目控制价下浮\d%即为成交价|成交原则|不得确定为(中标|成交)|招标人按下列原则选择中标人|评选成交供应商:|拟邀请供应商|除单一来源采购项目外|单一来源除外|(各.{,5}|尊敬的)(供应商|供货商)[:\s]|竞拍起止时间:|询价结果[\s\n::]*不公开|本项目已具备招标条件|现对该项目进行招标公告|发布\w{2}结果后\d天内送达|本次\w{2}结果不对外公示|供应商\s*资格要求|成交情况:\s*[流废]标',
       # |确定成交供应商[:,\s]
       # |确定成交供应商[:,\s]
           '合同公告': '合同(公告|公示|信息|内容)|合同(编号|名称|主体|基本情况|签订日期)|(供应商乙方|乙方供应商):|合同总?金额',
           '合同公告': '合同(公告|公示|信息|内容)|合同(编号|名称|主体|基本情况|签订日期)|(供应商乙方|乙方供应商):|合同总?金额',
           '废标公告': '(终止|中止|废标|流标|失败|作废|异常|撤销)(结果)?(公告|公示|招标|采购|竞价)|(谈判结果为|结果类型):?废标|((本|该)(项目|标段|合同|合同包|采购包|次)\w{,5})((失败|终止|流标|废标)|予以废标|(按|做|作)?(流标|废标)处理)|(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|竞谈|应答|项目)(终止|中止|废标|流标|失败|作废|异常|撤销)',
           '废标公告': '(终止|中止|废标|流标|失败|作废|异常|撤销)(结果)?(公告|公示|招标|采购|竞价)|(谈判结果为|结果类型):?废标|((本|该)(项目|标段|合同|合同包|采购包|次)\w{,5})((失败|终止|流标|废标)|予以废标|(按|做|作)?(流标|废标)处理)|(采购|招标|询价|议价|竞价|比价|比选|遴选|邀请|邀标|磋商|洽谈|约谈|谈判|竞谈|应答|项目)(终止|中止|废标|流标|失败|作废|异常|撤销)',
-          '废标公告2': '(无效|中止|终止|废标|流标|失败|作废|异常|撤销)的?(原因|理由)|本项目因故取消|本(项目|次)(公开)?\w{2}失败|已终止\s*原因:|(人|人数|供应商|单位)(不足|未达\w{,3}数量)|已终止|不足[3三]家|无(废标)'
+          '废标公告2': '(无效|中止|终止|废标|流标|失败|作废|异常|撤销)的?(原因|理由)|本项目因故取消|本(项目|次)(公开)?\w{2}失败|已终止\s*原因:|(人|人数|供应商|单位)(不足|未达\w{,3}数量)|已终止|不足[3三]家|无(废标)|成交情况:\s*[流废]标'
       }
       }
       self.title_life_dic = {
       self.title_life_dic = {
           '采购意向': '采购意向|招标意向|选取意向|意向公告|意向公示|意向公开',
           '采购意向': '采购意向|招标意向|选取意向|意向公告|意向公示|意向公开',