kvtree_search.py 4.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. @author: bidikeji
  5. @time: 2024/12/26 10:31
  6. """
  7. from BiddingKG.dl.interface.html_2_kvtree import Html2KVTree
  8. from BiddingKG.dl.common.Utils import timeFormat
  9. import re
  10. requirement_pattern = "(采购需求|需求分析|项目说明|(采购|合同|招标|询比?价|项目|服务|工程|标的|需求|建设)(的?(主要|简要|基本|具体|名称及))?" \
  11. "(内容|概况|概述|范围|信息|规模|简介|介绍|说明|摘要|情况)([及与和]((其它|\w{,2})[要需]求|发包范围|数量))?" \
  12. "|招标项目技术要求|服务要求|服务需求|项目目标|需求内容如下|建设规模)为?([::,]|$)"
  13. aptitude_pattern = "资质(资格)要求|资格(资质)要求|单位要求|资质及业绩要求|((资格|资质|准入)[的及]?(要求|条件|标准|限定|门槛)|竞买资格及要求|供应商报价须知)|按以下要求参与竞买|((报名|应征|竞买|投标|竞投|受让|报价|竞价|竞包|竞租|承租|申请|参与|参选|遴选)的?(人|方|单位|企业|客户|机构)?|供应商|受让方)((必?须|需|应[该当]?)(具备|满足|符合|提供)+以?下?)?的?(一般|基本|主要)?(条件|要求|资格(能力)?|资质)+|乙方应当符合下列要求|参与比选条件|合格的投标人|询价要求|项目要求"
  14. pinmu_name_pattern = "采购品目(名称)?([::,]|$)"
  15. addr_bidopen_pattern = "([开评]标|开启|评选|比选|磋商|遴选|寻源|采购|招标|竞价|议价|委托|询比?价|比价|谈判|邀标|邀请|洽谈|约谈|选取|抽取|抽选|递交\w{,4}文件)[))]?(时间[与及和、])?(地址|地点)([与及和、]时间)?([::,]|$)"
  16. addr_bidsend_pattern = "((\w{,4}文件)?(提交|递交)(\w{,4}文件)?|投标)(截止时间[与及和、])?地[点址]([与及和、]截止时间)?([::,]|$)"
  17. change_content_pattern = "(变更|更正)(事项[与及和、])?(信息|内容|事项)|现做出如下变更|变更内容如下"
  18. change_time_pattern = "(变更|更正)日期"
  19. pattern_dic_single = {
  20. 'requirement': requirement_pattern,
  21. 'aptitude': aptitude_pattern,
  22. 'pinmu_name': pinmu_name_pattern,
  23. 'change_content': change_content_pattern,
  24. 'change_time': change_time_pattern
  25. }
  26. pattern_dic_addr = {
  27. 'addr_bidopen': addr_bidopen_pattern,
  28. 'addr_bidsend': addr_bidsend_pattern
  29. }
  30. def get_kvtree_value(html):
  31. '''
  32. 通过kv数解析,正则匹配 k 值获取内容
  33. :param html:
  34. :return:
  35. '''
  36. _pd = Html2KVTree(html)
  37. kv_single_dic = {} # 单独放在外面的字段
  38. kv_addr_dic = {} # 放在地址字典的字段
  39. for k, v in pattern_dic_single.items():
  40. kv_l = _pd.extract_kv(v)
  41. value = ''
  42. for d in kv_l:
  43. ser = re.search(v, d.get('key', ''))
  44. if ser and ser.end()/len(d.get('key', ''))<0.5: # 571545382 过滤错误提取,例 供应商要求澄清采购文件的截止时间 提取到 供应商要求 aptitude
  45. continue
  46. elif d.get('key', '').strip() == d.get('value', '').strip(): # 修复 571425136 k: aptitude, key: 1.供应商资质, value: 1.供应商资质
  47. continue
  48. if d.get('value', '').strip() != '':
  49. value = d['value'].strip()
  50. break
  51. if value != '':
  52. if 'time' in k:
  53. value = timeFormat(value)
  54. if value != '':
  55. kv_single_dic[k] = value
  56. elif re.search('[\u4e00-\u9fa5]{2,}', value): # 包含两个中文以上的才要
  57. if k == 'change_content':
  58. value = re.sub('\n+', '', value)[:500] # 变更内容去掉空格并限制200字
  59. kv_single_dic[k] = value
  60. for k, v in pattern_dic_addr.items():
  61. kv_l = _pd.extract_kv(v)
  62. value = ''
  63. for d in kv_l:
  64. if d.get('value', '').strip() != '':
  65. value = d['value'].strip()
  66. if re.search('时间:', value) and re.search('地[点址]:(?P<addr>[\w()()【】-]{5,50})[,。]', value):
  67. value = re.search('地[点址]:(?P<addr>[\w()()【】-]{5,50})[,。]', value).group('addr')
  68. break
  69. if value != '' and re.search('\w{2,5}[省市区]|\d号|\w{2,12}自治[区州县旗]|采购网|平台|公司', value): # 包含两个中文以上的才要 避免 571236792 文件获取地点:-- 这种也提取
  70. kv_addr_dic[k] = value
  71. return kv_single_dic, kv_addr_dic
  72. if __name__ == "__main__":
  73. with open('d:/html/2.html', encoding='utf-8') as f:
  74. html = f.read()
  75. rs = get_kvtree_value(html)
  76. # print(rs)
  77. d1, d2 = rs
  78. for k, v in d1.items():
  79. print(k, v)