re_bidway.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. import ast
  2. import pandas as pd
  3. import re
  4. # from BiddingKG.dl.interface import Entitys
  5. # def re_bidway_old(text):
  6. # df = pd.read_csv("C:\\Users\\admin\\Desktop\\bidway_text.csv")
  7. #
  8. # reg = re.compile(u'(采购方式|竞价方式|招标方式|询价类型|交易方式|寻源策略|招标形式|询价方式'
  9. # u'|发包方式|发包类型|开展方式|招标类型)(.*)'
  10. # u'(公开招标|竞争性磋商|竞争性谈判|公开采购|单一来源'
  11. # u'|电子书面竞投|邀请招标|定向公开|询价采购|抽签摇号'
  12. # u'|网上电子投标|比质比价|询单|询比采购|比选|单一来源采购'
  13. # u'|网上招标|其他'
  14. # u'|竞谈竞价|网上直购|公开竞谈'
  15. # u'|库内邀请|库内公开发包)')
  16. #
  17. # # reg = re.compile(u'(公开招标|竞争性磋商|竞争性谈判采购|公开采购|单一来源|网络竞价'
  18. # # u'|竞争性谈判|公开询价|邀请招标|公开招募|公开询比价|电子书面竞投'
  19. # # u'|网上电子投标|比质比价|定向询单|国内比选|电子竞价'
  20. # # u'|公开招租|公开竞标方式|网上招标|公开招标|国内竞争性谈判'
  21. # # u'|国内竞争性磋商|公开竞谈|定向询价|网上询价|网上竞价|公开比选|磋商采购|网上直购'
  22. # # u'|库内邀请|询价采购|询比采购|分散采购|单一来源采购)')
  23. #
  24. # reg2 = re.compile(u'(采用|以|)'
  25. # u'(公开招标|竞争性磋商|竞争性谈判|公开采购|单一来源'
  26. # u'|竞争性谈判|询价|电子书面竞投|电子竞价'
  27. # u'|网上电子投标|比质比价|询单|询比采购|比选|单一来源采购'
  28. # u'|网上招标|分散采购'
  29. # u'|竞谈竞价|网上直购|公开竞谈'
  30. # u'|库内邀请)'
  31. # u'(采购方式|方式)')
  32. #
  33. # reg1 = re.compile(
  34. # # u'(公开招标|竞争性磋商|竞争性谈判采购|公开采购|单一来源采购|网络竞价|公开招商方式'
  35. # # u'|竞争性谈判|公开询价|询价采购|邀请招标|公开招募|公开询比|电子书面竞投'
  36. # # u'|网上电子投标|比质比价|定向询单|询比采购|国内比选|单一来源|公开选取|库内公开发包'
  37. # # u'|公开招租|公开竞标方式|网上招标|公开招标|竞争性谈判|公开招投标'
  38. # # u'|国内竞争性磋商|公开竞谈|定向询价|网上询价|网上竞价|公开比选|磋商采购|网上直购'
  39. # # u'|国际公开竞争性招标)'
  40. # u'(公开招标|竞争性磋商|竞争性谈判|公开采购|单一来源'
  41. # u'|竞争性谈判|询价|电子书面竞投'
  42. # u'|网上电子投标|比质比价|询单|询比采购|比选|单一来源采购'
  43. # u'|网上招标|分散采购'
  44. # u'|竞谈竞价|网上直购|公开竞谈'
  45. # u'|库内邀请)'
  46. # )
  47. #
  48. # # 都切为4个字符
  49. # # reg1_not = re.compile(u'(及单一来源|询价小组成员|除单一来源|竞争性谈判邀请函|询价记录)')
  50. # reg1_not = re.compile(u'(及单一来|价小组成|除单一来|性谈判邀|询价记录)')
  51. #
  52. # reg3 = re.compile(u'(采购方式:邀请|采购方式:公开|采购方式:询价|分散采购|公开招标|竞价|磋商|询比|竞标|邀请招标|公开招募|公开招租)')
  53. #
  54. #
  55. # reg_standard = re.compile(u'(公开招标|竞争性磋商|竞争性谈判|单一来源'
  56. # u'|竞争性谈判|询价|邀请招标|公开招募|询比|电子书面竞投'
  57. # u'|网上电子投标|比质比价|询单|比选'
  58. # u'|公开招租|网上招标|分散采购'
  59. # u'|网上直购|公开竞谈|采购方式:邀请|采购方式:公开|采购方式:询价)'
  60. # )
  61. #
  62. # text_list = df["text"].to_list()
  63. # # text_list = []
  64. # # text_list.append(text)
  65. # text_index_list = []
  66. # output_list = []
  67. # for index in range(len(text_list)):
  68. # # 全文下标
  69. # text_index = [0, 0]
  70. #
  71. # input_str = text_list[index]
  72. #
  73. # # 把一些混淆的词先替换掉
  74. # input_str = re.sub(reg1_not, "####", input_str)
  75. #
  76. # match = reg.search(input_str)
  77. # output_str = None
  78. # # 根据正则表达式匹配
  79. # if match:
  80. # # 更新全文下标
  81. # text_index[0] = match.start()
  82. # text_index[1] = match.end()
  83. #
  84. # # 判断长度,截断
  85. # if len(match.group()) >= 15:
  86. # ss = re.split(",|\.|,|。|;|;", match.group())
  87. # # 判断所需的字符串在哪一段
  88. # for i in range(len(ss)):
  89. # if re.search(reg1, ss[i]):
  90. # output_str = ss[i]
  91. #
  92. # # 更新全文下标
  93. # front_len, back_len = calculateLen(ss, i)
  94. # text_index[0] = text_index[0] + front_len + i
  95. # text_index[1] = text_index[1] - back_len + len(ss) -1 - i
  96. #
  97. # break
  98. # else:
  99. # output_str = match.group()
  100. #
  101. # else:
  102. # match2 = re.search(reg2, input_str)
  103. # if match2:
  104. # # 更新全文下标
  105. # text_index[0] = match2.start()
  106. # text_index[1] = match2.end()
  107. #
  108. # output_str = match2.group()
  109. #
  110. # else:
  111. # match1 = re.search(reg1, input_str)
  112. # if match1:
  113. # # 更新全文下标
  114. # text_index[0] = match1.start()
  115. # text_index[1] = match1.end()
  116. # output_str = match1.group()
  117. #
  118. # # 再判断一次长度
  119. # if output_str is not None:
  120. # if len(output_str) >= 15:
  121. # match2 = re.search(reg2, input_str)
  122. # if match2:
  123. # # 更新全文下标
  124. # text_index[0] = match2.start()
  125. # text_index[1] = match2.end()
  126. #
  127. # output_str = match2.group()
  128. # if len(output_str) >= 15:
  129. # match1 = re.search(reg1, input_str)
  130. # if match1:
  131. # # 更新全文下标
  132. # text_index[0] = match1.start()
  133. # text_index[1] = match1.end()
  134. #
  135. # output_str = match1.group()
  136. #
  137. # # 最后输出还为空,匹配一些易混淆的词
  138. # if output_str is None:
  139. # match3 = re.search(reg3, input_str)
  140. # if match3:
  141. # # 更新全文下标
  142. # text_index[0] = match3.start()
  143. # text_index[1] = match3.end()
  144. #
  145. # output_str = match3.group()
  146. #
  147. # # 处理前缀等无用词
  148. # if output_str is not None:
  149. # match5 = re.search("分散采购|采购方式:邀请", output_str)
  150. # if not match5:
  151. # # 公开采购转为公开招标
  152. # output_str = re.sub("公开采购", "公开招标", output_str)
  153. #
  154. # # 去掉第一个字符冒号
  155. # ss = re.split(":|:", output_str)
  156. # output_str = ss[-1]
  157. # # 更新全文下标
  158. # front_len, back_len = calculateLen(ss, len(ss) - 1)
  159. # text_index[0] = text_index[0] + front_len + len(ss) - 1
  160. #
  161. # # 去掉采购、方式、采用
  162. # match6 = re.search("(采用|出售|直接(|现就本次|招标为)", output_str)
  163. # match7 = re.search("(采购|方式|进行)", output_str)
  164. # output_str = re.sub("(采购|方式|采用|出售|进行|直接(|现就本次|招标为)", "", output_str)
  165. # # 更新全文下标
  166. # if match6:
  167. # text_index[0] += match6.end() - match6.start()
  168. # if match7:
  169. # text_index[1] -= match7.end() - match7.start()
  170. #
  171. # # 使用标准标签过滤
  172. # match4 = re.search(reg_standard, output_str)
  173. # if match4:
  174. # output_str = match4.group()
  175. # # 更新全文下标
  176. # text_index[0] += match4.start()
  177. # text_index[1] = text_index[0] + match4.end() - match4.start()
  178. #
  179. # output_list.append(output_str)
  180. # # text_index_list.append(str(text_index))
  181. # text_index_list.append(text_index)
  182. #
  183. # # df["re"] = pd.DataFrame(output_list)
  184. # # df["text_index"] = pd.DataFrame(text_index_list)
  185. #
  186. # # index_to_word = []
  187. # # for index, row in df.iterrows():
  188. # # i_list = ast.literal_eval(row["text_index"])
  189. # # word = row["text"][i_list[0]:i_list[1]]
  190. # # if len(word) >= 20:
  191. # # word = ""
  192. # # index_to_word.append(word)
  193. #
  194. #
  195. # # df["index2word"] = pd.DataFrame(index_to_word)
  196. # # df.to_csv("C:\\Users\\admin\\Desktop\\bidway_text2.csv")
  197. #
  198. # return output_list[0], text_index_list[0]
  199. bidway = '单一来源' \
  200. '|国内竞争性磋商|竞争性磋商|竞争性谈判|网络竞价|网上竞价|公开竞谈|公开竞价|电子竞价|竞价|竞标|竞谈竞价|电子书面竞投' \
  201. '|公开比选|比质比价|比选' \
  202. '|公开招标|公开招租|公开招募|公开选取|公开招投标' \
  203. '|网上直购|网上招标|网上电子投标|网上挂牌' \
  204. '|邀请招标' \
  205. '|网上询价|公开询价|非定向询价|定向询价|询比价|询单|询价|询比' \
  206. '|库内邀请|库内公开发包|内部邀标' \
  207. '|定点采购议价|定点采购' \
  208. '|竞争性评审'
  209. not_bidway = '及单一来源|询价小组成员|除单一来源|竞争性谈判邀请函|询价记录|自由竞价' \
  210. '|限时竞价|咨询单位|询价单'
  211. not_bidway_preffix = "本次|拟|参加|无效|标的|联合体|参与|否决|除"
  212. not_bidway_suffix = "文件|报名|邀请|项目|失败|数量|编号|后|时间|类型|名称|和|成交" \
  213. "|标题|开始|结束|产品|报价|供应商|部门|监督|需求|范围|入围|内容|人" \
  214. "|条件|公司|保证金|完毕|事件|成功|活动|地点|标|会|须知|范围" \
  215. "|响应|报价|采购公示|的原因|采购供应商|价|采购人员|失败"
  216. bidway_preffix = '采购方式|竞价方式|招标方式|询价类型|交易方式|寻源策略|招标形式|询价方式' \
  217. '|发包方式|发包类型|开展方式|招标类型|选取方式|招租方式'
  218. bidway_special = '采购方式:公开|采购方式:邀请|采购方式:询价' \
  219. '|招标方式:.公开|采购方式:.公开' \
  220. '|分散采购' \
  221. ''
  222. def re_not_bidway(_str):
  223. match = re.findall(not_bidway, _str)
  224. if match:
  225. for word in match:
  226. instead = "#" * len(word)
  227. _str = re.sub(word, instead, _str)
  228. reg_not1 = "(" + bidway + ")" + "(" + not_bidway_suffix + ")"
  229. match = re.findall(reg_not1, _str)
  230. if match:
  231. for word in match:
  232. word_add = ""
  233. for w in word:
  234. word_add += w
  235. instead = "#" * len(word_add)
  236. _str = re.sub(word_add, instead, _str)
  237. reg_not2 = "(" + not_bidway_preffix + ")" + "(" + bidway + ")"
  238. match = re.findall(reg_not2, _str)
  239. if match:
  240. for word in match:
  241. word_add = ""
  242. for w in word:
  243. word_add += w
  244. instead = "#" * len(word_add)
  245. _str = re.sub(word_add, instead, _str)
  246. return _str
  247. def re_standard_bidway(_str):
  248. reg_standard = "(?P<preffix>" + bidway_preffix + ")" \
  249. + "(?P<char>.{1,2})" \
  250. + "(?P<value>" + bidway + ")"
  251. match = re.finditer(reg_standard, _str)
  252. bidway_list = []
  253. if match:
  254. for m in match:
  255. m_dict = m.groupdict()
  256. m_span = m.span()
  257. keyword = ""
  258. keyword_index = [m_span[0], m_span[1]]
  259. for key in m_dict.keys():
  260. if key == "value":
  261. keyword = m_dict.get(key)
  262. else:
  263. keyword_index[0] += len(m_dict.get(key))
  264. bidway_list.append([keyword, keyword_index])
  265. return bidway_list
  266. def re_all_bidway(_str):
  267. reg_all = "(?P<value>" + bidway + ")"
  268. match = re.finditer(reg_all, _str)
  269. bidway_list = []
  270. if match:
  271. for m in match:
  272. keyword = m.group()
  273. keyword_index = list(m.span())
  274. bidway_list.append([keyword, keyword_index])
  275. return bidway_list
  276. def re_special_bidway(_str):
  277. reg_special = "(?P<value>" + bidway_special + ")"
  278. match = re.finditer(reg_special, _str)
  279. bidway_list = []
  280. if match:
  281. for m in match:
  282. keyword = m.group()
  283. keyword_index = list(m.span())
  284. bidway_list.append([keyword, keyword_index])
  285. return bidway_list
  286. def get_one_word(bidway_list):
  287. # 若有多个,去重,输出较长的
  288. word = None
  289. text_index = [0, 0]
  290. if len(bidway_list) > 1:
  291. word_dict = {}
  292. for bw in bidway_list:
  293. if bw[0] in word_dict.keys():
  294. if bw[1][0] < word_dict.get(bw[0])[0]:
  295. word_dict[bw[0]] = bw[1]
  296. else:
  297. word_dict[bw[0]] = bw[1]
  298. word_list = []
  299. for key in word_dict.keys():
  300. word_list.append([key, word_dict.get(key)[0]])
  301. if len(word_list) > 1:
  302. word_list.sort(key=lambda x: (-int(x[1]), len(x[0])))
  303. word = word_list[-1][0]
  304. text_index = word_dict.get(word)
  305. elif word_list:
  306. word = word_list[0][0]
  307. text_index = word_dict.get(word)
  308. else:
  309. text_index = [0, 0]
  310. elif len(bidway_list) == 1:
  311. word = bidway_list[0][0]
  312. text_index = bidway_list[0][1]
  313. return word, text_index
  314. def re_bidway(text, title):
  315. # 替换易混淆词
  316. text_clean = re_not_bidway(text)
  317. title_clean = re_not_bidway(title)
  318. # 查找符合标准形式的
  319. bidway_list = re_standard_bidway(text_clean)
  320. if bidway_list:
  321. word = bidway_list[0][0]
  322. text_index = bidway_list[0][1]
  323. return word, text_index
  324. # 无符合标准形式的,查找title里的所有形式
  325. bidway_list = re_all_bidway(title_clean)
  326. if bidway_list:
  327. word, text_index = get_one_word(bidway_list)
  328. return word, text_index
  329. # 无符合标准形式的,查找所有形式
  330. bidway_list = re_all_bidway(text_clean)
  331. if bidway_list:
  332. word, text_index = get_one_word(bidway_list)
  333. return word, text_index
  334. # 还无结果,查找特殊形式
  335. bidway_list = re_special_bidway(text_clean)
  336. if bidway_list:
  337. word = bidway_list[0][0]
  338. text_index = bidway_list[0][1]
  339. return word, text_index
  340. # 查无结果
  341. return None, [0, 0]
  342. def extract_bidway(text, title):
  343. list_bidway = []
  344. word, text_index_list = re_bidway(text, title)
  345. if word is not None:
  346. if text_index_list[1]-text_index_list[0] != len(word) \
  347. or text_index_list[1]-text_index_list[0] >= 10:
  348. return []
  349. d = {"body": word, "begin_index": text_index_list[0], "end_index": text_index_list[1]}
  350. list_bidway.append(d)
  351. # print(d.get("body"), d.get("begin_index"), d.get("end_index"))
  352. return list_bidway
  353. def test_csv():
  354. df = pd.read_csv("C:\\Users\\Administrator\\Desktop\\bidway_text.csv")
  355. predict_list = []
  356. for index, row in df.iterrows():
  357. word, text_index = re_bidway(row["text"], "")
  358. if word:
  359. predict = [word, text_index]
  360. else:
  361. predict = []
  362. print("predict", predict)
  363. predict_list.append(str(predict))
  364. predict_df = pd.DataFrame(predict_list)
  365. df = pd.concat([df, predict_df], axis=1)
  366. df.to_csv("C:\\Users\\Administrator\\Desktop\\bidway_result.csv")
  367. print("finish write!")
  368. def test_str():
  369. s = '政府采购项目招标方式:公开招标,联系人:黎明。代理机构地址:广州市天河区'
  370. s = '''
  371. ,关于人防工程技术咨询服务项目【重新招标】单一来源谈判的通知,各投标人:深圳市国际招标有限公司受中共
  372. 深圳市委军民融合发展委员会办公室委托,就人防工程技术咨询服务项目【重新招标】(项目编号:0658-2171
  373. 1A60965),进行公开招标,因投标单位不足三家,公开招标失败,现经采购单位同意,采用单一来源谈判方式
  374. 确定中标供应商,邀请中国建筑标准设计研究院有限公司前来谈判,一、项目编号:0658-21711A60965,二
  375. 、项目名称:人防工程技术咨询服务项目【重新招标】,三、凡被邀请参加谈判的供应商必须按照原招标文件第
  376. 六章要求制作谈判文件正本一本,副本二本,按规定的时间密封递交并参加谈判,四、谈判内容:投标价格、项
  377. 目实施方案、售后服务方案和其它相关事项,五、地点及时间:1、因疫情影响本项目谈判响应文件采用邮寄方
  378. 式接收文件,2、文件接收截止时间:2021年11月5日14:30(北京时间),3、谈判响应文件邮寄地址:深圳
  379. 市罗湖区嘉宾路2018号深华商业大厦裙楼6层600A。收件人:郑工,电话:18806665013,3、谈判地点:
  380. 线上谈判,六、谈判的相关规则按原招标文件的相应规定执行;有关谈判事宜详见招标文件第六章《公开招标失
  381. 败后后续采购程序和投标须知》,1、采购人信息,名称:中共深圳市委军民融合发展委员会办公室,地址:深
  382. 圳市福田区新洲路5008号,联系方式:刘先生,电话:0755-88100332,2、采购代理机构信息,名称:深
  383. 圳市国际招标有限公司,地址:罗湖总部:深圳市罗湖区嘉宾路2018号深华商业大厦裙楼6层,深圳湾总部:深
  384. 圳市南山区沙河西路与白石路交汇处深圳湾科技生态园9栋B4座6楼,联系方式:0755-22918634,监督举报
  385. 电话:0755-22965602、0755-86660475,特此通知,深圳市国际招标有限公司,2021年11月1日,更多
  386. 咨询报价请点击:http://zbcloud.net/bidbulletin/69495.htm,
  387. '''
  388. print(extract_bidway(s, title=""))
  389. def test_html():
  390. html_path = "C:/Users/Administrator/Desktop/3.html"
  391. with open(html_path, "r") as f:
  392. s = f.read()
  393. print(extract_bidway(s, title=""))
  394. if __name__ == "__main__":
  395. # extract_bidway(s)
  396. test_csv()
  397. # test_str()
  398. # test_html()