getAttributes.py 169 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933
  1. from BiddingKG.dl.common.Utils import findAllIndex,debug,timeFormat,getCurrent_date
  2. from BiddingKG.dl.interface.Entitys import PREM,Role,Entity
  3. from decimal import Decimal
  4. import re
  5. import copy
  6. import math
  7. import pandas as pd
  8. import os
  9. from scipy.optimize import linear_sum_assignment
  10. from BiddingKG.dl.interface.Entitys import Match
  11. import numpy as np
  12. def getTheRole(entity,role_list):
  13. '''
  14. @summary:根据实体名称拿到index
  15. @param:
  16. entity:实体名称
  17. role_list:角色list
  18. @return:该实体所在下标
  19. '''
  20. for role_index in range(len(role_list)):
  21. if entity in role_list[role_index]:
  22. return role_index
  23. return None
  24. dict_role_id = {"0":"tenderee",
  25. "1":"agency",
  26. "2":"win_tenderer",
  27. "3":"second_tenderer",
  28. "4":"third_tenderer"}
  29. def getPackage(packageList,sentence_index,begin_index,roleid,MAX_DIS=None,DIRECT=None):
  30. '''
  31. @param:
  32. packageList:文章的包的信息,包号-sent_index-词偏移-字偏移-[[前作用域句子,句内偏移],[后作用域句子,句内偏移]]-匹配集合
  33. sentence_index:实体所在的句子
  34. begin_index:实体所在句子的起始位置
  35. @return:公司实体所属的包
  36. @summary: 优化多标段,确定标段作用域之后,寻找作用域包含该实体的所有包,从前往后找到一个还没有该roleid的包返回,若找到的包都有roleid,则返回第一个,若没有找到包,返回None
  37. '''
  38. '''
  39. if len(packageList)==0:
  40. return None
  41. before_index = None
  42. after_index = None
  43. equal_index = None
  44. equal_count = 0
  45. for pack_index in range(len(packageList)):
  46. if packageList[pack_index][1]>sentence_index and after_index is None:
  47. after_index = pack_index
  48. if packageList[pack_index][1]<sentence_index:
  49. before_index = pack_index
  50. if packageList[pack_index][1]==sentence_index and equal_index is None:
  51. equal_index = pack_index
  52. #当前句子和之前句子未找到包
  53. if before_index is None and equal_index is None:
  54. return None
  55. else:
  56. if after_index is None:
  57. end_index = len(packageList)
  58. else:
  59. end_index = after_index
  60. #只在当前句子找到一个包号
  61. if end_index-max((before_index if before_index is not None else -1,equal_index if equal_index is not None else -1))==1:
  62. return packageList[end_index-1][0]
  63. else:
  64. for i in range(max((before_index if before_index is not None else -1,equal_index if equal_index is not None else -1)),end_index):
  65. if packageList[i][2]>int(begin_index):
  66. if packageList[i-1][4]:
  67. return packageList[i-1][0]
  68. else:
  69. if packageList[i][4]:
  70. return packageList[i-1][0]
  71. else:
  72. return packageList[i][0]
  73. return packageList[end_index-1][0]
  74. '''
  75. if len(packageList)==0:
  76. return None,False
  77. list_legalPack = []
  78. for pack_index in range(len(packageList)):
  79. if DIRECT=="L" and (packageList[pack_index]["sentence_index"]>sentence_index or (packageList[pack_index]["sentence_index"]==sentence_index and packageList[pack_index]["offsetWords_begin"]>begin_index)):
  80. continue
  81. if DIRECT=="R" and (packageList[pack_index]["sentence_index"]<sentence_index or (packageList[pack_index]["sentence_index"]==sentence_index and packageList[pack_index]["offsetwords_begin"]<begin_index)):
  82. continue
  83. if (packageList[pack_index]["scope"][0][0]<sentence_index or (packageList[pack_index]["scope"][0][0]==sentence_index and packageList[pack_index]["scope"][0][1]<=begin_index)) and (packageList[pack_index]["scope"][1][0]>sentence_index or (packageList[pack_index]["scope"][1][0]==sentence_index and packageList[pack_index]["scope"][1][1]>=begin_index)):
  84. if MAX_DIS is not None:
  85. if abs(sentence_index-packageList[pack_index]["sentence_index"])<=MAX_DIS:
  86. list_legalPack.append(pack_index)
  87. else:
  88. list_legalPack.append(pack_index)
  89. # if (packageList[pack_index]["scope"][0][0] < sentence_index
  90. # or (packageList[pack_index]["scope"][0][0] == sentence_index
  91. # and packageList[pack_index]["scope"][0][1] <= begin_index))
  92. # and (packageList[pack_index]["scope"][1][0] > sentence_index
  93. # or (packageList[pack_index]["scope"][1][0] == sentence_index
  94. # and packageList[pack_index]["scope"][1][1] >= begin_index)):
  95. # pass
  96. _flag = True
  97. for _index in list_legalPack:
  98. if roleid in packageList[_index]["hit"]:
  99. continue
  100. else:
  101. _flag = False
  102. packageList[_index]["hit"].add(roleid)
  103. return packageList[_index]["pointer"],_flag
  104. if len(list_legalPack)>0:
  105. return packageList[0]["pointer"],_flag
  106. return None,False
  107. #生成合法的组合
  108. def get_legal_comba(list_entity,dict_role_combination):
  109. #拿到一个包中所有合法的组合
  110. def circle_package(_dict_legal_combination):
  111. list_dict_role_first = []
  112. for _role in _dict_legal_combination:
  113. if len(list_dict_role_first)==0:
  114. for _entity in _dict_legal_combination[_role]:
  115. if _entity !="":
  116. list_dict_role_first.append({_role:_entity})
  117. else:
  118. list_dict_role_after = []
  119. _find_count = 0
  120. for _entity in _dict_legal_combination[_role]:
  121. if _entity !="":
  122. for _dict in list_dict_role_first:
  123. _flag = True
  124. for _key1 in _dict:
  125. if _entity==_dict[_key1]:
  126. #修改为招标人和代理人可以为同一个
  127. if str(_key1) in ["0","1"] and str(_role) in ["0","1"]:
  128. _flag = True
  129. else:
  130. _flag = False
  131. if _flag:
  132. _find_count += 1
  133. _new_dict = copy.copy(_dict)
  134. _new_dict[_role] = _entity
  135. if len(list_dict_role_after)>100000:
  136. break
  137. list_dict_role_after.append(_new_dict)
  138. else:
  139. # 2021/5/25 update,同一实体(entity_text)不同角色
  140. if len(list_dict_role_after) > 100000:
  141. break
  142. for _dict in list_dict_role_first:
  143. for _key1 in _dict:
  144. if _entity == _dict[_key1]:
  145. _new_dict = copy.copy(_dict)
  146. _new_dict.pop(_key1)
  147. _new_dict[_role] = _entity
  148. list_dict_role_after.append({_role:_entity})
  149. if len(list_dict_role_after)==0:
  150. pass
  151. else:
  152. list_dict_role_first.extend(list_dict_role_after)
  153. return list_dict_role_first
  154. def recursive_package(_dict_legal_combination,set_legal_entity,dict_one_selution,list_all_selution):
  155. last_layer = False
  156. #若是空组合则放回空
  157. if len(_dict_legal_combination.keys())==0:
  158. return []
  159. #递归到最后一层则修改状态
  160. if len(_dict_legal_combination.keys())==1:
  161. last_layer = True
  162. #取一个角色开始进行遍历
  163. _key_role = list(_dict_legal_combination.keys())[0]
  164. for item in _dict_legal_combination[_key_role]:
  165. copy_dict_one_selution = copy.copy(dict_one_selution)
  166. copy_dict_legal_combination = {}
  167. copy_set_legal_entity = copy.copy(set_legal_entity)
  168. #复制余下的所有角色,进行下一轮递归
  169. for _key in _dict_legal_combination.keys():
  170. if _key!=_key_role:
  171. copy_dict_legal_combination[_key] = _dict_legal_combination[_key]
  172. #修改为招标人和代理人可以为同一个
  173. if item !="":
  174. _flag = True
  175. if str(_key_role) in ["0","1"]:
  176. for _key_flag in copy_dict_one_selution:
  177. if _key_flag not in ["0","1"] and copy_dict_one_selution[_key_flag]==item:
  178. _flag = False
  179. else:
  180. for _key_flag in copy_dict_one_selution:
  181. if copy_dict_one_selution[_key_flag]==item:
  182. _flag = False
  183. if _flag:
  184. copy_dict_one_selution[_key_role] = item
  185. '''
  186. if item not in copy_set_legal_entity:
  187. if item !="":
  188. copy_dict_one_selution[_key_role] = item
  189. '''
  190. copy_set_legal_entity.add(item)
  191. if last_layer:
  192. list_all_selution.append(copy_dict_one_selution)
  193. else:
  194. recursive_package(copy_dict_legal_combination,copy_set_legal_entity,copy_dict_one_selution,list_all_selution)
  195. #递归匹配各个包的结果
  196. def recursive_packages(_dict_legal_combination,dict_one_selution,list_all_selution):
  197. last_layer = False
  198. if len(_dict_legal_combination.keys())==0:
  199. return []
  200. if len(_dict_legal_combination.keys())==1:
  201. last_layer = True
  202. _key_pack = list(_dict_legal_combination.keys())[0]
  203. for item in _dict_legal_combination[_key_pack]:
  204. copy_dict_one_selution = copy.copy(dict_one_selution)
  205. copy_dict_legal_combination = {}
  206. for _key in _dict_legal_combination.keys():
  207. if _key!=_key_pack:
  208. copy_dict_legal_combination[_key] = _dict_legal_combination[_key]
  209. for _key_role in item.keys():
  210. copy_dict_one_selution[_key_pack+"$$"+_key_role] = item[_key_role]
  211. if last_layer:
  212. list_all_selution.append(copy_dict_one_selution)
  213. else:
  214. recursive_packages(copy_dict_legal_combination,copy_dict_one_selution,list_all_selution)
  215. return list_all_selution
  216. #循环获取所有包组合
  217. def circle_pageages(_dict_legal_combination):
  218. list_all_selution = []
  219. for _key_pack in _dict_legal_combination.keys():
  220. list_key_selution = []
  221. for item in _dict_legal_combination[_key_pack]:
  222. _dict = dict()
  223. for _key_role in item.keys():
  224. _dict[_key_pack+"$$"+_key_role] = item[_key_role]
  225. list_key_selution.append(_dict)
  226. if len(list_all_selution)==0:
  227. list_all_selution = list_key_selution
  228. else:
  229. _list_all_selution = []
  230. for item_1 in list_all_selution:
  231. for item_2 in list_key_selution:
  232. _list_all_selution.append(dict(item_1,**item_2))
  233. list_all_selution = _list_all_selution
  234. return list_all_selution
  235. #拿到各个包解析之后的结果
  236. _dict_legal_combination = {}
  237. for packageName in dict_role_combination.keys():
  238. _list_all_selution = []
  239. # recursive_package(dict_role_combination[packageName], set(), {}, _list_all_selution)
  240. _list_all_selution = circle_package(dict_role_combination[packageName])
  241. '''
  242. # print("===1")
  243. # print(packageName)
  244. for item in _list_all_selution:
  245. # print(item)
  246. # print("===2")
  247. '''
  248. #去除包含子集
  249. list_all_selution_simple = []
  250. _list_set_all_selution = []
  251. for item_selution in _list_all_selution:
  252. item_set_selution = set()
  253. for _key in item_selution.keys():
  254. item_set_selution.add((_key,item_selution[_key]))
  255. _list_set_all_selution.append(item_set_selution)
  256. if len(_list_set_all_selution)>1000:
  257. _dict_legal_combination[packageName] = _list_all_selution
  258. continue
  259. for i in range(len(_list_set_all_selution)):
  260. be_included = False
  261. for j in range(len(_list_set_all_selution)):
  262. if i!=j:
  263. if len(set(_list_set_all_selution[i])&set(_list_set_all_selution[j]))==len(_list_set_all_selution[i]) and len(_list_set_all_selution[i])!=len(_list_set_all_selution[j]):
  264. be_included = True
  265. if not be_included:
  266. list_all_selution_simple.append(_list_all_selution[i])
  267. _dict_legal_combination[packageName] = list_all_selution_simple
  268. _list_final_comba = []
  269. #对各个包的结果进行排列组合
  270. _comba_count = 1
  271. for _key in _dict_legal_combination.keys():
  272. _comba_count *= len(_dict_legal_combination[_key])
  273. #如果过大,则每个包只取概率最大的那个
  274. dict_pack_entity_prob = get_dict_entity_prob(list_entity)
  275. if _comba_count>250:
  276. new_dict_legal_combination = dict()
  277. for _key_pack in _dict_legal_combination.keys():
  278. MAX_PROB = -1000
  279. _MAX_PROB_COMBA = None
  280. for item in _dict_legal_combination[_key_pack]:
  281. # print(_key_pack,item)
  282. _dict = dict()
  283. for _key in item.keys():
  284. _dict[str(_key_pack)+"$$"+str(_key)] = item[_key]
  285. _prob = getSumExpectation(dict_pack_entity_prob, _dict)
  286. if _prob>MAX_PROB:
  287. MAX_PROB = _prob
  288. _MAX_PROB_COMBA = [item]
  289. if _MAX_PROB_COMBA is not None:
  290. new_dict_legal_combination[_key_pack] = _MAX_PROB_COMBA
  291. _dict_legal_combination = new_dict_legal_combination
  292. #recursive_packages(_dict_legal_combination, {}, _list_final_comba)
  293. _list_final_comba = circle_pageages(_dict_legal_combination)
  294. #除了Project包(招标人和代理人),其他包是不会有冲突的
  295. #查看是否有一个实体出现在了Project包和其他包中,如有,要进行裁剪
  296. _list_real_comba = []
  297. for dict_item in _list_final_comba:
  298. set_project = set()
  299. set_other = set()
  300. for _key in list(dict_item.keys()):
  301. if _key.split("$$")[0]=="Project":
  302. set_project.add(dict_item[_key])
  303. else:
  304. set_other.add(dict_item[_key])
  305. set_common = set_project&set_other
  306. if len(set_common)>0:
  307. dict_project = {}
  308. dict_not_project = {}
  309. for _key in list(dict_item.keys()):
  310. if dict_item[_key] in set_common:
  311. if str(_key.split("$$")[0])=="Project":
  312. dict_project[_key] = dict_item[_key]
  313. else:
  314. dict_not_project[_key] = dict_item[_key]
  315. else:
  316. dict_project[_key] = dict_item[_key]
  317. dict_not_project[_key] = dict_item[_key]
  318. _list_real_comba.append(dict_project)
  319. _list_real_comba.append(dict_not_project)
  320. else:
  321. _list_real_comba.append(dict_item)
  322. return _list_real_comba
  323. def get_dict_entity_prob(list_entity,on_value=0.5):
  324. dict_pack_entity_prob = {}
  325. for in_attachment in [False,True]:
  326. identified_role = []
  327. if in_attachment==True:
  328. identified_role = [value[0] for value in dict_pack_entity_prob.values()]
  329. for entity in list_entity:
  330. if entity.entity_type in ['org','company'] and entity.in_attachment==in_attachment:
  331. values = entity.values
  332. role_prob = float(values[int(entity.label)])
  333. _key = entity.packageName+"$$"+str(entity.label)
  334. if role_prob>=on_value and str(entity.label)!="5":
  335. _key_prob = _key+"$text$"+entity.entity_text
  336. if in_attachment == True:
  337. if entity.entity_text in identified_role:
  338. continue
  339. if _key_prob in dict_pack_entity_prob:
  340. if role_prob>dict_pack_entity_prob[_key_prob][1]:
  341. dict_pack_entity_prob[_key_prob] = [entity.entity_text,role_prob]
  342. else:
  343. dict_pack_entity_prob[_key_prob] = [entity.entity_text,role_prob]
  344. return dict_pack_entity_prob
  345. #计算合计期望
  346. def getSumExpectation(dict_pack_entity_prob,combination,on_value=0.5):
  347. '''
  348. expect = 0
  349. for entity in list_entity:
  350. if entity.entity_type in ['org','company']:
  351. values = entity.values
  352. role_prob = float(values[int(entity.label)])
  353. _key = entity.packageName+"$$"+str(entity.label)
  354. if role_prob>on_value and str(entity.label)!="5":
  355. if _key in combination.keys() and combination[_key]==entity.entity_text:
  356. expect += math.pow(role_prob,4)
  357. else:
  358. expect -= math.pow(role_prob,4)
  359. '''
  360. #修改为同一个实体只取对应包-角色的最大的概率值
  361. expect = 0
  362. dict_entity_prob = {}
  363. for _key_pack_entity in dict_pack_entity_prob:
  364. _key_pack = _key_pack_entity.split("$text$")[0]
  365. role_prob = dict_pack_entity_prob[_key_pack_entity][1]
  366. if _key_pack in combination.keys() and combination[_key_pack]==dict_pack_entity_prob[_key_pack_entity][0]:
  367. if _key_pack_entity in dict_entity_prob.keys():
  368. if dict_entity_prob[_key_pack_entity]<role_prob:
  369. dict_entity_prob[_key_pack_entity] = role_prob
  370. else:
  371. dict_entity_prob[_key_pack_entity] = role_prob
  372. else:
  373. if _key_pack_entity in dict_entity_prob.keys():
  374. if dict_entity_prob[_key_pack_entity]>-role_prob:
  375. dict_entity_prob[_key_pack_entity] = -role_prob
  376. else:
  377. dict_entity_prob[_key_pack_entity] = -role_prob
  378. # for entity in list_entity:
  379. # if entity.entity_type in ['org','company']:
  380. # values = entity.values
  381. # role_prob = float(values[int(entity.label)])
  382. # _key = entity.packageName+"$$"+str(entity.label)
  383. # if role_prob>=on_value and str(entity.label)!="5":
  384. # if _key in combination.keys() and combination[_key]==entity.entity_text:
  385. # _key_prob = _key+entity.entity_text
  386. # if _key_prob in dict_entity_prob.keys():
  387. # if dict_entity_prob[_key_prob]<role_prob:
  388. # dict_entity_prob[_key_prob] = role_prob
  389. # else:
  390. # dict_entity_prob[_key_prob] = role_prob
  391. # else:
  392. # _key_prob = _key+entity.entity_text
  393. # if _key_prob in dict_entity_prob.keys():
  394. # if dict_entity_prob[_key_prob]>-role_prob:
  395. # dict_entity_prob[_key_prob] = -role_prob
  396. # else:
  397. # dict_entity_prob[_key_prob] = -role_prob
  398. for _key in dict_entity_prob.keys():
  399. symbol = 1 if dict_entity_prob[_key]>0 else -1
  400. expect += symbol*math.pow(dict_entity_prob[_key],2)
  401. return expect
  402. def getRoleList(list_sentence,list_entity,on_value = 0.5):
  403. '''
  404. @summary: 搜索树,得到所有不矛盾的角色组合,取合计期望值最大的作为结果返回
  405. @param:
  406. list_sentence:文章所有的sentence
  407. list_entity:文章所有的实体
  408. on_value:概率阈值
  409. @return:文章的角色list
  410. '''
  411. pack = getPackagesFromArticle(list_sentence,list_entity)
  412. if pack is None:
  413. return None
  414. PackageList,PackageSet,dict_PackageCode = pack
  415. #拿到所有可能的情况
  416. dict_role_combination = {}
  417. # print(PackageList)
  418. #拿到各个实体的packageName,packageCode
  419. for entity in list_entity:
  420. if entity.entity_type in ['org','company']:
  421. #限制附件里角色values[label]最大概率prob
  422. max_prob = 0.85
  423. if str(entity.label)!="5" and entity.in_attachment:
  424. if entity.values[entity.label]>max_prob:
  425. entity.values[entity.label] = max_prob
  426. #过滤掉字数小于3个的实体
  427. if len(entity.entity_text)<=3:
  428. continue
  429. values = entity.values
  430. role_prob = float(values[int(entity.label)])
  431. if role_prob>=on_value and str(entity.label)!="5":
  432. if str(entity.label) in ["0","1"]:
  433. packageName = "Project"
  434. else:
  435. if len(PackageSet)>0:
  436. packagePointer,_ = getPackage(PackageList,entity.sentence_index,entity.begin_index,"role-"+str(entity.label))
  437. if packagePointer is None:
  438. #continue
  439. packageName = "Project"
  440. # print(entity.entity_text, packageName,entity.sentence_index,entity.begin_index)
  441. else:
  442. #add pointer_pack
  443. entity.pointer_pack = packagePointer
  444. packageName = packagePointer.entity_text
  445. # print(entity.entity_text, packageName)
  446. else:
  447. packageName = "Project"
  448. find_flag = False
  449. if packageName in dict_PackageCode.keys():
  450. packageCode = dict_PackageCode[packageName]
  451. else:
  452. packageCode = ""
  453. entity.packageCode = packageCode
  454. role_name = dict_role_id.get(str(entity.label))
  455. entity.roleName = role_name
  456. entity.packageName = packageName
  457. if entity.packageName in dict_role_combination.keys():
  458. if str(entity.label) in dict_role_combination[entity.packageName].keys():
  459. dict_role_combination[entity.packageName][str(entity.label)].add(entity.entity_text)
  460. else:
  461. dict_role_combination[entity.packageName][str(entity.label)] = set([entity.entity_text])
  462. else:
  463. dict_role_combination[entity.packageName] = {}
  464. #初始化空值
  465. roleIds = [0,1,2,3,4]
  466. for _roleId in roleIds:
  467. dict_role_combination[entity.packageName][str(_roleId)] = set([""])
  468. dict_role_combination[entity.packageName][str(entity.label)].add(entity.entity_text)
  469. list_real_comba = get_legal_comba(list_entity,dict_role_combination)
  470. # print("===role_combination",dict_role_combination)
  471. # print("== real_comba",list_real_comba)
  472. #拿到最大期望值的组合
  473. max_index = 0
  474. max_expect = -100
  475. _index = 0
  476. dict_pack_entity_prob = get_dict_entity_prob(list_entity)
  477. for item_combination in list_real_comba:
  478. expect = getSumExpectation(dict_pack_entity_prob, item_combination)
  479. if expect>max_expect:
  480. max_index = _index
  481. max_expect = expect
  482. _index += 1
  483. RoleList = []
  484. RoleSet = set()
  485. if len(list_real_comba)>0:
  486. for _key in list_real_comba[max_index].keys():
  487. packageName = _key.split("$$")[0]
  488. label = _key.split("$$")[1]
  489. role_name = dict_role_id.get(str(label))
  490. entity_text = list_real_comba[max_index][_key]
  491. if packageName in dict_PackageCode.keys():
  492. packagecode = dict_PackageCode.get(packageName)
  493. else:
  494. packagecode = ""
  495. RoleList.append(PREM(packageName,packagecode,role_name,entity_text,0,0,0.0,[]))
  496. RoleSet.add(entity_text)
  497. #根据最优树来修正list_entity中角色对包的连接
  498. for _entity in list_entity:
  499. if _entity.pointer_pack is not None:
  500. _pack_name = _entity.pointer_pack.entity_text
  501. _find_flag = False
  502. for _prem in RoleList:
  503. if _prem.packageName==_pack_name and _prem.entity_text==_entity.entity_text:
  504. _find_flag = True
  505. if not _find_flag:
  506. _entity.pointer_pack = None
  507. return RoleList,RoleSet,PackageList,PackageSet
  508. def getPackageScopePattern():
  509. '''
  510. @summary: 获取包的作用域关键词
  511. '''
  512. df = pd.read_excel(os.path.dirname(__file__)+"/end.xls")
  513. pattern = "("
  514. for item in df["list_word"]:
  515. item = str(item).replace("(","\(").replace(")","\)").replace(".","\.").replace("[","\[").replace("]","\]").replace("-","\-")
  516. pattern += item+"|"
  517. pattern = pattern[:-1]+")[::是为]|业绩.{,30}标段[0-9A-Za-z一二三四五六七八九十]{0,3}"
  518. return pattern
  519. pattern_packageScope = getPackageScopePattern()
  520. def getPackagesFromArticle(list_sentence,list_entity):
  521. '''
  522. @param:
  523. list_sentence:文章的句子list
  524. @summary: 将包的信息插入list_entity中
  525. @return: type:list if [包号,句子index,词偏移,标段号] meaning:文章的包/标段信息
  526. '''
  527. if len(list_sentence)==0:
  528. return None
  529. list_sentence.sort(key=lambda x:x.sentence_index)
  530. PackageList = []
  531. PackageList_scope = []
  532. PackageSet = set()
  533. dict_packageCode = dict()
  534. package_name_pattern = re.compile("((标[段号的包]|分包)的?(名[称单]?|包名))[::]?([^::]{3,30}?),{1}")
  535. package_N_name_pattern = re.compile("(([^承]|^)分?包|标段|标包|标|包|包组|子项目|包件|项目类型)编?号?[::]?[\((]?([0-9A-Za-z一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]){1,2},{1}")
  536. package_number_pattern = re.compile("(((([^承]|^)包|标[段号的包]|分?包|包组|包件)编?号?|子项目|项目类型)[::]?[0-9A-Za-z一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}[^\.])[^至]?|([^\.]?第[ⅠⅡⅢⅣⅤⅥⅦ0-9A-Za-z一二三四五六七八九十]{1,4}(包号|标[段号的包]|分?包))") # 第? 去掉问号 修复 纯木浆8包/箱复印 这种作为包号
  537. # other_package_pattern = re.compile('(项目名称|物资名称|设备名称|场次名称|标段名称)[::](.{,20}?)(,|项目)') # 新正则识别标段
  538. other_package_pattern = re.compile('((项目|物资|设备|场次|标段|标的|产品)(名称)?)[::]([^,。]{2,50}?)[,。]') # # 2020/11/23 大网站规则 调整 package_N_name_pattern, package_N_name_pattern 中的项目 改为 子项目
  539. win_tenderer_pattern = re.compile('(中标候?选?人|供应商)(名称)?[::](.{2,25})[,。]') # 2020/11/23 大网站规则 调整
  540. model_pattern = re.compile('(型号|序号)[::]([^,。]{2,20})[,。]') # 2020/11/23 大网站规则 调整
  541. number_pattern = re.compile("[0-9A-Za-z一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦ]{1,4}")
  542. package_code_pattern = re.compile("(?:编号[::]?\s*)([-\dA-Za-z\(\)]+)")
  543. # 纯数字类型的包号统一,例如:'01','1'
  544. re_digital = re.compile("^\d+$")
  545. def changeIndexFromWordToWords(tokens,word_index):
  546. '''
  547. @summary:转换某个字的字偏移为词偏移
  548. '''
  549. before_index = 0
  550. after_index = 0
  551. for i in range(len(tokens)):
  552. after_index = after_index+len(tokens[i])
  553. if before_index<=word_index and after_index>=word_index:
  554. return i
  555. before_index = after_index
  556. package_names = []
  557. def extractPackageCode(tokens,word_index,size=20,pattern = package_code_pattern):
  558. '''
  559. @summary:抽取包附近的标段号
  560. @param:
  561. tokens:包所在句子的分词
  562. word_index:包所在字偏移
  563. size:左右各取多少个词
  564. pattern:提取标段号的正则
  565. @return: type:string,meaning:标段号
  566. '''
  567. index = changeIndexFromWordToWords(tokens,word_index)
  568. if index<size:
  569. begin = index
  570. else:
  571. begin = index-size
  572. if index+size>len(tokens):
  573. end = len(tokens)
  574. else:
  575. end = index+size
  576. #拿到左右两边的词语组成短语
  577. text = "".join(tokens[begin:end])
  578. #在短语中的字偏移
  579. new_word_index = word_index-len("".join(tokens[:begin]))
  580. min_distance = len(text)
  581. packageCode = None
  582. for the_iter in re.finditer(pattern,text):
  583. #算出最小距离
  584. distance = min([abs(new_word_index-the_iter.span()[0]),abs(new_word_index-the_iter.span()[1])])
  585. if distance<min_distance:
  586. min_distance = distance
  587. packageCode = the_iter.group(1)
  588. return packageCode
  589. #从标段介绍表格中提取包名和包号
  590. for i in range(len(list_sentence)):
  591. content = list_sentence[i].sentence_text
  592. names = re.findall(package_name_pattern,content)
  593. if names == []:
  594. names = re.findall(other_package_pattern, content)
  595. N_names = re.findall(package_N_name_pattern,content)
  596. if len(names)==1 and len(N_names)==1:
  597. package_names.append([names[0][-1],N_names[0][-1]])
  598. for i in range(len(list_sentence)):
  599. PackageList_item = []
  600. PackageList_item_scope = []
  601. content = list_sentence[i].sentence_text
  602. tokens = list_sentence[i].tokens
  603. _names = []
  604. # 2021/6/23 包名称去重
  605. for name in package_names:
  606. if name not in _names:
  607. _names.append(name)
  608. # for name in package_names[:20]:
  609. for name in _names[:20]:
  610. for index in findAllIndex(name[0],content):
  611. temp_package_number = re.findall(number_pattern,name[1])[0]
  612. if re.search(re_digital,temp_package_number):
  613. temp_package_number = str(int(temp_package_number))
  614. PackageList_item.append({"name":temp_package_number,"sentence_index":list_sentence[i].sentence_index,"offsetWords_begin":changeIndexFromWordToWords(tokens,index),"offsetWord_begin":index,"offsetWord_end":index+len(name[0])})
  615. # PackageList_item.append([temp_package_number,i,changeIndexFromWordToWords(tokens,index),index,index+len(str(temp_package_number))])
  616. code = extractPackageCode(tokens, index)
  617. if code is not None:
  618. dict_packageCode[temp_package_number] = code
  619. PackageSet.add(temp_package_number)
  620. for iter in re.finditer(package_number_pattern,content):
  621. temp_package_number = re.findall(number_pattern,content[iter.span()[0]:iter.span()[1]])[0]
  622. if re.search(re_digital, temp_package_number):
  623. temp_package_number = str(int(temp_package_number))
  624. 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]})
  625. # PackageList_item.append([temp_package_number,i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
  626. code = extractPackageCode(tokens, iter.span()[0])
  627. if code is not None:
  628. dict_packageCode[temp_package_number] = code
  629. PackageSet.add(temp_package_number)
  630. #识别packageScope
  631. for iter in re.finditer(pattern_packageScope,content):
  632. 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]})
  633. # PackageList_item_scope.append(["",i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
  634. PackageList_item_scope = PackageList_item +PackageList_item_scope
  635. PackageList_item_scope.sort(key=lambda x:x["offsetWord_begin"])
  636. PackageList_scope = PackageList_scope+PackageList_item_scope
  637. PackageList_item.sort(key=lambda x:x["sentence_index"])
  638. #PackageList = PackageList+PackageList_item
  639. #不作为包
  640. # if len(PackageSet)==0:
  641. # for i in range(len(list_sentence)):
  642. # PackageList_item = []
  643. # PackageList_item_scope = []
  644. # content = list_sentence[i].sentence_text
  645. # tokens = list_sentence[i].tokens
  646. # for iter in re.finditer(other_package_pattern,content):
  647. # temp_package_number = iter.group(2)
  648. # 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]})
  649. # # PackageList_item.append([temp_package_number,i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
  650. # code = extractPackageCode(tokens, iter.span()[0])
  651. # if code is not None:
  652. # dict_packageCode[temp_package_number] = code
  653. # PackageSet.add(temp_package_number)
  654. # #识别packageScope
  655. # for iter in re.finditer(pattern_packageScope,content):
  656. # 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]})
  657. # # PackageList_item_scope.append(["",i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
  658. # PackageList_item_scope = PackageList_item +PackageList_item_scope
  659. # PackageList_item_scope.sort(key=lambda x:x["offsetWord_begin"])
  660. # PackageList_scope = PackageList_scope+PackageList_item_scope
  661. # PackageList_item.sort(key=lambda x:x["sentence_index"])
  662. # 2020/11/23 大网站规则 调整
  663. 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:
  664. for i in range(len(list_sentence)):
  665. PackageList_item = []
  666. PackageList_item_scope = []
  667. content = list_sentence[i].sentence_text
  668. tokens = list_sentence[i].tokens
  669. names = re.findall(other_package_pattern, content)
  670. N_names = re.findall(win_tenderer_pattern, content)
  671. if len(names) != 1 or len(N_names) != 1:
  672. continue
  673. for iter in re.finditer(other_package_pattern,content):
  674. temp_package_number = iter.group(4)
  675. xinghao = re.search(model_pattern, content)
  676. if xinghao:
  677. temp_package_number = temp_package_number + '+' + xinghao.group(2)
  678. # print('新正则采购包名补充',temp_package_number)
  679. if re.search(re_digital,temp_package_number):
  680. temp_package_number = str(int(temp_package_number))
  681. 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]})
  682. # PackageList_item.append([temp_package_number,i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
  683. code = extractPackageCode(tokens, iter.span()[0])
  684. if code is not None:
  685. dict_packageCode[temp_package_number] = code
  686. PackageSet.add(temp_package_number)
  687. #识别packageScope
  688. for iter in re.finditer(pattern_packageScope,content):
  689. 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]})
  690. # PackageList_item_scope.append(["",i,changeIndexFromWordToWords(tokens,iter.span()[0]),iter.span()[0],iter.span()[1]])
  691. PackageList_item_scope = PackageList_item +PackageList_item_scope
  692. PackageList_item_scope.sort(key=lambda x:x["offsetWord_begin"])
  693. PackageList_scope = PackageList_scope+PackageList_item_scope
  694. PackageList_item.sort(key=lambda x:x["sentence_index"])
  695. pattern_punctuation = "[::()\(\),,。;;]"
  696. # print("===packageList_scope",PackageList_scope)
  697. for i in range(len(list_sentence)):
  698. for j in range(len(PackageList_scope)):
  699. if i==PackageList_scope[j]["sentence_index"] and PackageList_scope[j]["name"]!="":
  700. _flag = False
  701. left_str = list_sentence[i].sentence_text[PackageList_scope[j]["offsetWord_begin"]-30:PackageList_scope[j]["offsetWord_begin"]+1]
  702. right_str = list_sentence[i].sentence_text[PackageList_scope[j]["offsetWord_begin"]:PackageList_scope[j]["offsetWord_begin"]+30]
  703. _left_find = re.findall(pattern_punctuation,left_str)
  704. _right_find = re.findall(pattern_punctuation,right_str)
  705. #print(left_str)
  706. if re.search("同",left_str[-1:]) is not None and PackageList_scope[j]["name"]=="一":
  707. continue
  708. if re.search("划分",right_str[:10]) is not None:
  709. continue
  710. if len(_left_find)>0 and _left_find[-1] in [":",":"]:
  711. _flag = True
  712. if len(_right_find)>0 and _right_find[0] in [":",":"]:
  713. _flag = True
  714. if _flag:
  715. scope_begin = [PackageList_scope[j]["sentence_index"],PackageList_scope[j]["offsetWords_begin"]]
  716. else:
  717. if j==0:
  718. scope_begin = [0,0]
  719. else:
  720. scope_begin = [PackageList_scope[j-1]["sentence_index"],PackageList_scope[j-1]["offsetWords_begin"]]
  721. if j==len(PackageList_scope)-1:
  722. scope_end = [list_sentence[-1].sentence_index,changeIndexFromWordToWords(list_sentence[-1].tokens, len(list_sentence[-1].sentence_text))]
  723. else:
  724. scope_end = [PackageList_scope[j+1]["sentence_index"],PackageList_scope[j+1]["offsetWords_begin"]]
  725. 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"]:
  726. continue
  727. #add package to entity
  728. _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)
  729. list_entity.append(_pack_entity)
  730. copy_pack = copy.copy(PackageList_scope[j])
  731. copy_pack["scope"] = [scope_begin,scope_end]
  732. copy_pack["hit"] = set()
  733. copy_pack["pointer"] = _pack_entity
  734. PackageList.append(copy_pack)
  735. return PackageList,PackageSet,dict_packageCode
  736. # km配对方法
  737. def dispatch(match_list):
  738. main_roles = list(set([match.main_role for match in match_list]))
  739. attributes = list(set([match.attribute for match in match_list]))
  740. label = np.zeros(shape=(len(main_roles), len(attributes)))
  741. for match in match_list:
  742. main_role = match.main_role
  743. attribute = match.attribute
  744. value = match.value
  745. label[main_roles.index(main_role), attributes.index(attribute)] = value + 10000
  746. # print(label)
  747. gragh = -label
  748. # km算法
  749. row, col = linear_sum_assignment(gragh)
  750. max_dispatch = [(i, j) for i, j, value in zip(row, col, gragh[row, col]) if value]
  751. # return [Match(main_roles[row], attributes[col]) for row, col in max_dispatch]
  752. return [(main_roles[row], attributes[col]) for row, col in max_dispatch]
  753. from BiddingKG.dl.common.Utils import getUnifyMoney
  754. from BiddingKG.dl.interface.modelFactory import Model_relation_extraction
  755. relationExtraction_model = Model_relation_extraction()
  756. def findAttributeAfterEntity(PackDict,roleSet,PackageList,PackageSet,list_sentence,list_entity,list_outline,on_value = 0.5,on_value_person=0.5,sentence_len=4):
  757. '''
  758. @param:
  759. PackDict:文章包dict
  760. roleSet:文章所有角色的公司名称
  761. PackageList:文章的包信息
  762. PackageSet:文章所有包的名称
  763. list_entity:文章所有经过模型处理的实体
  764. on_value:金额模型的阈值
  765. on_value_person:联系人模型的阈值
  766. sentence_len:公司和属性间隔句子的最大长度
  767. @return:添加了属性信息的角色list
  768. '''
  769. #根据roleid添加金额到rolelist中
  770. def addMoneyByRoleid(packDict,packageName,roleid,money,money_prob):
  771. for i in range(len(packDict[packageName]["roleList"])):
  772. if packDict[packageName]["roleList"][i].role_name==dict_role_id.get(str(roleid)):
  773. if money_prob>packDict[packageName]["roleList"][i].money_prob:
  774. packDict[packageName]["roleList"][i].money = money
  775. packDict[packageName]["roleList"][i].money_prob = money_prob
  776. return packDict
  777. #根据实体名称添加金额到rolelist中
  778. def addMoneyByEntity(packDict,packageName,entity,money,money_prob):
  779. for i in range(len(packDict[packageName]["roleList"])):
  780. if packDict[packageName]["roleList"][i].entity_text==entity:
  781. # if money_prob>packDict[packageName]["roleList"][i].money_prob:
  782. # packDict[packageName]["roleList"][i].money = money
  783. # packDict[packageName]["roleList"][i].money_prob = money_prob
  784. if packDict[packageName]["roleList"][i].money_prob==0 : # 2021/7/20第一次更新金额
  785. packDict[packageName]["roleList"][i].money = money.entity_text
  786. packDict[packageName]["roleList"][i].money_prob = money_prob
  787. packDict[packageName]["roleList"][i].money_unit = money.money_unit
  788. elif money_prob>packDict[packageName]["roleList"][i].money_prob+0.2 or (money.notes in ['大写'] and money.in_attachment==False): # 2021/7/20改为优先选择大写金额,
  789. # print('已连接金额概率:money_prob:',packDict[packageName]["roleList"][i].money_prob)
  790. # print('链接金额备注 ',money.notes, money.entity_text, money.values)
  791. packDict[packageName]["roleList"][i].money = money.entity_text
  792. packDict[packageName]["roleList"][i].money_prob = money_prob
  793. packDict[packageName]["roleList"][i].money_unit = money.money_unit
  794. # print('链接中的金额:{0}, 单位:{1}'.format(money.entity_text, money.money_unit))
  795. return packDict
  796. def addRatioByEntity(packDict,packageName,entity,ratio):
  797. for i in range(len(packDict[packageName]["roleList"])):
  798. if packDict[packageName]["roleList"][i].entity_text==entity:
  799. packDict[packageName]["roleList"][i].ratio = ratio.entity_text
  800. def addServiceTimeByEntity(packDict,packageName,entity,serviceTime):
  801. for i in range(len(packDict[packageName]["roleList"])):
  802. if packDict[packageName]["roleList"][i].entity_text==entity:
  803. packDict[packageName]["roleList"][i].serviceTime = serviceTime.entity_text
  804. #根据实体名称得到角色
  805. def getRoleWithText(packDict,entity_text):
  806. for pack in packDict.keys():
  807. for i in range(len(packDict[pack]["roleList"])):
  808. if packDict[pack]["roleList"][i].entity_text==entity_text:
  809. return packDict[pack]["roleList"][i].role_name
  810. def doesEntityOrLinkedEntity_inRoleSet(entity,RoleSet):
  811. _list_entitys = [entity]+entity.linked_entitys
  812. for _entity in _list_entitys:
  813. if _entity.entity_text in RoleSet:
  814. return True
  815. p_entity = 0
  816. # 2021/7/19 顺序比较金额,前面是后面的一万倍则把前面金额/10000
  817. money_list = [it for it in list_entity if it.entity_type=="money"]
  818. for i in range(len(money_list)-1):
  819. for j in range(1, len(money_list)):
  820. if (float(money_list[i].entity_text) > 5000000000 or money_list[j].notes=='大写') and \
  821. Decimal(money_list[i].entity_text)/Decimal(money_list[j].entity_text)==10000:
  822. money_list[i].entity_text = str(Decimal(money_list[i].entity_text)/10000)
  823. # print('连接前修改大于50亿金额:前面是后面的一万倍则把前面金额/10000')
  824. #遍历所有实体
  825. # while(p_entity<len(list_entity)):
  826. # entity = list_entity[p_entity]
  827. '''
  828. #招标金额从后往前找
  829. if entity.entity_type=="money":
  830. if entity.values[entity.label]>=on_value:
  831. if str(entity.label)=="0":
  832. packagePointer,_ = getPackage(PackageList,entity.sentence_index,entity.begin_index,"money-"+str(entity.label))
  833. if packagePointer is None:
  834. packageName = "Project"
  835. else:
  836. packageName = packagePointer.entity_text
  837. addMoneyByRoleid(PackDict, packageName, "0", entity.entity_text, entity.values[entity.label])
  838. '''
  839. ''' # 2020/11/25 与下面的联系人连接步骤重复,取消
  840. if entity.entity_type=="person":
  841. if entity.values[entity.label]>=on_value_person:
  842. if str(entity.label)=="1":
  843. for i in range(len(PackDict["Project"]["roleList"])):
  844. if PackDict["Project"]["roleList"][i].role_name=="tenderee":
  845. PackDict["Project"]["roleList"][i].linklist.append((entity.entity_text,entity.person_phone))
  846. # add pointer_person
  847. for _entity in list_entity:
  848. if dict_role_id.get(str(_entity.label))=="tenderee":
  849. for i in range(len(PackDict["Project"]["roleList"])):
  850. if PackDict["Project"]["roleList"][i].entity_text==_entity.entity_text and PackDict["Project"]["roleList"][i].role_name=="tenderee":
  851. _entity.pointer_person = entity
  852. elif str(entity.label)=="2":
  853. for i in range(len(PackDict["Project"]["roleList"])):
  854. if PackDict["Project"]["roleList"][i].role_name=="agency":
  855. PackDict["Project"]["roleList"][i].linklist.append((entity.entity_text,entity.person_phone))
  856. # add pointer_person
  857. for _entity in list_entity:
  858. if dict_role_id.get(str(_entity.label))=="agency":
  859. for i in range(len(PackDict["Project"]["roleList"])):
  860. if PackDict["Project"]["roleList"][i].entity_text==_entity.entity_text and PackDict["Project"]["roleList"][i].role_name=="agency":
  861. _entity.pointer_person = entity
  862. '''
  863. # #金额往前找实体
  864. # if entity.entity_type=="money":
  865. # if entity.values[entity.label]>=on_value:
  866. # p_entity_money= p_entity
  867. # entity_money = list_entity[p_entity_money]
  868. # if len(PackageSet)>0:
  869. # packagePointer,_ = getPackage(PackageList,entity_money.sentence_index,entity_money.begin_index,"money-"+str(entity_money.entity_text)+"-"+str(entity_money.label))
  870. # if packagePointer is None:
  871. # packageName_entity = "Project"
  872. # else:
  873. # packageName_entity = packagePointer.entity_text
  874. # else:
  875. # packageName_entity = "Project"
  876. # while(p_entity_money>0):
  877. # entity_before = list_entity[p_entity_money]
  878. # if entity_before.entity_type in ['org','company']:
  879. # if str(entity_before.label)=="1":
  880. # addMoneyByEntity(PackDict, packageName_entity, entity_before.entity_text, entity_money.entity_text, entity_money.values[entity_money.label])
  881. # #add pointer_money
  882. # entity_before.pointer_money = entity_money
  883. # break
  884. # p_entity_money -= 1
  885. #如果实体属于角色集合,则往后找属性
  886. # if doesEntityOrLinkedEntity_inRoleSet(entity, roleSet):
  887. #
  888. # p_entity += 1
  889. # #循环查找符合的属性
  890. # while(p_entity<len(list_entity)):
  891. #
  892. # entity_after = list_entity[p_entity]
  893. # if entity_after.sentence_index-entity.sentence_index>=sentence_len:
  894. # p_entity -= 1
  895. # break
  896. # #若是遇到公司实体,则跳出循环
  897. # if entity_after.entity_type in ['org','company']:
  898. # p_entity -= 1
  899. # break
  900. # if entity_after.values is not None:
  901. # if entity_after.entity_type=="money":
  902. # if entity_after.values[entity_after.label]>=on_value:
  903. # '''
  904. # #招标金额从后往前找
  905. # if str(entity_after.label)=="0":
  906. # packagePointer,_ = getPackage(PackageList,entity.sentence_index,entity.begin_index,"money-"+str(entity.label))
  907. # if packagePointer is None:
  908. # packageName = "Project"
  909. # else:
  910. # packageName = packagePointer.entity_text
  911. # addMoneyByRoleid(PackDict, packageName, "0", entity_after.entity_text, entity_after.values[entity_after.label])
  912. # '''
  913. # if str(entity_after.label)=="1":
  914. # #print(entity_after.entity_text,entity.entity_text)
  915. # _list_entitys = [entity]+entity.linked_entitys
  916. # if len(PackageSet)>0:
  917. # packagePointer,_ = getPackage(PackageList,entity_after.sentence_index,entity_after.begin_index,"money-"+str(entity_after.entity_text)+"-"+str(entity_after.label))
  918. # if packagePointer is None:
  919. # packageName_entity = "Project"
  920. # else:
  921. # packageName_entity = packagePointer.entity_text
  922. # else:
  923. # packageName_entity = "Project"
  924. # if str(entity.label) in ["2","3","4"]:
  925. # # addMoneyByEntity(PackDict, packageName_entity, entity.entity_text, entity_after.entity_text, entity_after.values[entity_after.label])
  926. # if entity_after.notes == '单价' or float(entity_after.entity_text)<5000: #2021/12/17 调整小金额阈值,避免203608823.html 两次金额一次万元没提取到的情况
  927. # addMoneyByEntity(PackDict, packageName_entity, entity.entity_text, entity_after,
  928. # 0.5)
  929. # entity.pointer_money = entity_after
  930. # # print('role zhao money', entity.entity_text, '中标金额:', entity_after.entity_text)
  931. # else:
  932. # addMoneyByEntity(PackDict, packageName_entity, entity.entity_text, entity_after,
  933. # entity_after.values[entity_after.label])
  934. # entity.pointer_money = entity_after
  935. # # print('role zhao money', entity.entity_text, '中标金额:', entity_after.entity_text)
  936. # if entity_after.values[entity_after.label]>0.6:
  937. # break # 2021/7/16 新增,找到中标金额,非单价即停止,不再往后找金额
  938. # #add pointer_money
  939. # # entity.pointer_money = entity_after
  940. # # print('role zhao money', entity.entity_text, '中标金额:', entity_after.entity_text)
  941. # # if entity_after.notes!='单价':
  942. # # break # 2021/7/16 新增,找到中标金额即停止,不再往后找金额
  943. # '''
  944. # if entity_after.entity_type=="person":
  945. # if entity_after.values[entity_after.label]>=on_value_person:
  946. # if str(entity_after.label)=="1":
  947. # for i in range(len(roleList)):
  948. # if roleList[i].role_name=="tenderee":
  949. # roleList[i].linklist.append((entity_after.entity_text,entity_after.person_phone))
  950. # elif str(entity_after.label)=="2":
  951. # for i in range(len(roleList)):
  952. # if roleList[i].role_name=="agency":
  953. # roleList[i].linklist.append((entity_after.entity_text,entity_after.person_phone))
  954. # elif str(entity_after.label)=="3":
  955. # _list_entitys = [entity]+entity.linked_entitys
  956. # for _entity in _list_entitys:
  957. # for i in range(len(roleList)):
  958. # if roleList[i].entity_text==_entity.entity_text:
  959. # if entity_after.sentence_index-_entity.sentence_index>1 and len(roleList[i].linklist)>0:
  960. # break
  961. # roleList[i].linklist.append((entity_after.entity_text,entity_after.person_phone))
  962. # '''
  963. #
  964. # p_entity += 1
  965. #
  966. # p_entity += 1
  967. # 记录每句的分词数量
  968. tokens_num_dict = dict()
  969. last_tokens_num = 0
  970. for sentence in list_sentence:
  971. _index = sentence.sentence_index
  972. if _index == 0:
  973. tokens_num_dict[_index] = 0
  974. else:
  975. tokens_num_dict[_index] = tokens_num_dict[_index - 1] + last_tokens_num
  976. last_tokens_num = len(sentence.tokens)
  977. attribute_type = ['money','serviceTime','ratio']# 'money'仅指“中投标金额”
  978. for link_attribute in attribute_type:
  979. temp_entity_list = []
  980. if link_attribute=="money":
  981. temp_entity_list = [ent for ent in list_entity if (ent.entity_type in ['org','company'] and ent.label in [2,3,4]) or
  982. (ent.entity_type=='money' and ent.label==1 and ent.values[ent.label]>=0.5)]
  983. # 删除重复的‘中投标金额’,一般为大小写两种样式
  984. drop_tendererMoney = []
  985. for ent_idx in range(len(temp_entity_list)-1):
  986. entity = temp_entity_list[ent_idx]
  987. if entity.entity_type=='money':
  988. next_entity = temp_entity_list[ent_idx+1]
  989. if next_entity.entity_type=='money':
  990. if getUnifyMoney(entity.entity_text)==getUnifyMoney(next_entity.entity_text):
  991. if (tokens_num_dict[next_entity.sentence_index] + next_entity.begin_index) - (
  992. tokens_num_dict[entity.sentence_index] + entity.end_index) < 10:
  993. drop_tendererMoney.append(next_entity)
  994. for _drop in drop_tendererMoney:
  995. temp_entity_list.remove(_drop)
  996. elif link_attribute=="serviceTime":
  997. temp_entity_list = [ent for ent in list_entity if (ent.entity_type in ['org','company'] and ent.label in [2,3,4]) or
  998. ent.entity_type=='serviceTime']
  999. elif link_attribute=="ratio":
  1000. temp_entity_list = [ent for ent in list_entity if (ent.entity_type in ['org','company'] and ent.label in [2,3,4]) or
  1001. ent.entity_type=='ratio']
  1002. temp_entity_list = sorted(temp_entity_list,key=lambda x: (x.sentence_index, x.begin_index))
  1003. temp_match_list = []
  1004. for ent_idx in range(len(temp_entity_list)):
  1005. entity = temp_entity_list[ent_idx]
  1006. if entity.entity_type in ['org','company']:
  1007. match_nums = 0
  1008. tenderer_nums = 0 #经过其他中投标人的数量
  1009. byNotTenderer_match_nums = 0 #跟在中投标人后面的属性
  1010. for after_index in range(ent_idx + 1, min(len(temp_entity_list), ent_idx + 4)):
  1011. after_entity = temp_entity_list[after_index]
  1012. if after_entity.entity_type == link_attribute:
  1013. distance = (tokens_num_dict[after_entity.sentence_index] + after_entity.begin_index) - (
  1014. tokens_num_dict[entity.sentence_index] + entity.end_index)
  1015. sentence_distance = after_entity.sentence_index - entity.sentence_index
  1016. value = (-1 / 2 * (distance ** 2)) / 10000
  1017. if link_attribute == "money":
  1018. if after_entity.notes == '单价':
  1019. value = value * 100
  1020. if sentence_distance == 0:
  1021. if distance < 100:
  1022. # value = (-1 / 2 * (distance ** 2)) / 10000
  1023. temp_match_list.append(Match(entity, after_entity, value))
  1024. match_nums += 1
  1025. if not tenderer_nums:
  1026. byNotTenderer_match_nums += 1
  1027. else:
  1028. break
  1029. else:
  1030. if distance < 60:
  1031. # value = (-1 / 2 * (distance ** 2)) / 10000
  1032. temp_match_list.append(Match(entity, after_entity, value))
  1033. match_nums += 1
  1034. if not tenderer_nums:
  1035. byNotTenderer_match_nums += 1
  1036. else:
  1037. break
  1038. else:
  1039. tenderer_nums += 1
  1040. #前向查找属性
  1041. if ent_idx!=0 and (not match_nums or not byNotTenderer_match_nums):
  1042. previous_entity = temp_entity_list[ent_idx - 1]
  1043. if previous_entity.entity_type == link_attribute:
  1044. # if previous_entity.sentence_index == entity.sentence_index:
  1045. distance = (tokens_num_dict[entity.sentence_index] + entity.begin_index) - (
  1046. tokens_num_dict[previous_entity.sentence_index] + previous_entity.end_index)
  1047. if distance < 40:
  1048. # 前向 没有 /10000
  1049. value = (-1 / 2 * (distance ** 2))
  1050. temp_match_list.append(Match(entity, previous_entity, value))
  1051. # km算法分配求解
  1052. dispatch_result = dispatch(temp_match_list)
  1053. dispatch_result = sorted(dispatch_result, key=lambda x: (x[0].sentence_index,x[0].begin_index))
  1054. for match in dispatch_result:
  1055. _entity = match[0]
  1056. _attribute = match[1]
  1057. if link_attribute=='money':
  1058. _entity.pointer_money = _attribute
  1059. packagePointer, _ = getPackage(PackageList, _attribute.sentence_index, _attribute.begin_index,
  1060. "money-" + str(_attribute.entity_text) + "-" + str(_attribute.label))
  1061. # print(_entity.entity_text,_attribute.entity_text)
  1062. if packagePointer is None:
  1063. packageName_entity = "Project"
  1064. else:
  1065. packageName_entity = packagePointer.entity_text
  1066. if _attribute.notes == '单价' or float(_attribute.entity_text) < 5000: # 2021/12/17 调整小金额阈值,避免203608823.html 两次金额一次万元没提取到的情况
  1067. # print(packageName_entity,_attribute.entity_text, _attribute.values[_attribute.label])
  1068. addMoneyByEntity(PackDict, packageName_entity, _entity.entity_text, _attribute,0.5)
  1069. else:
  1070. # print(packageName_entity,_attribute.entity_text, _attribute.values[_attribute.label])
  1071. addMoneyByEntity(PackDict, packageName_entity, _entity.entity_text, _attribute,
  1072. _attribute.values[_attribute.label])
  1073. elif link_attribute=='serviceTime':
  1074. _entity.pointer_serviceTime = _attribute
  1075. packagePointer, _ = getPackage(PackageList, _attribute.sentence_index, _attribute.begin_index,
  1076. "serviceTime-" + str(_attribute.entity_text) + "-" + str(_attribute.label))
  1077. if packagePointer is None:
  1078. packageName_entity = "Project"
  1079. else:
  1080. packageName_entity = packagePointer.entity_text
  1081. addServiceTimeByEntity(PackDict, packageName_entity, _entity.entity_text, _attribute)
  1082. elif link_attribute=='ratio':
  1083. _entity.pointer_ratio = _attribute
  1084. packagePointer, _ = getPackage(PackageList, _attribute.sentence_index, _attribute.begin_index,
  1085. "ratio-" + str(_attribute.entity_text) + "-" + str(_attribute.label))
  1086. if packagePointer is None:
  1087. packageName_entity = "Project"
  1088. else:
  1089. packageName_entity = packagePointer.entity_text
  1090. addRatioByEntity(PackDict, packageName_entity, _entity.entity_text, _attribute)
  1091. ''''''
  1092. # 通过模型分类的招标/代理联系人
  1093. list_sentence = sorted(list_sentence, key=lambda x: x.sentence_index)
  1094. person_list = [entity for entity in list_entity if entity.entity_type == 'person' and entity.label in [1, 2]]
  1095. tenderee_contact = set()
  1096. tenderee_phone = set()
  1097. agency_contact = set()
  1098. agency_phone = set()
  1099. winter_contact = set()
  1100. for _person in person_list:
  1101. if _person.label == 1:
  1102. tenderee_contact.add(_person.entity_text)
  1103. if _person.label == 2:
  1104. agency_contact.add(_person.entity_text)
  1105. # 正则匹配无 '主体/联系人' 的电话
  1106. # 例:"采购人联系方式:0833-5226788,"
  1107. phone_pattern = '(1[3-9][0-9][-—-―]?\d{4}[-—-―]?\d{4}|' \
  1108. '\+86.?1[3-9]\d{9}|' \
  1109. '0[1-9]\d{1,2}[-—-―][1-9]\d{6,7}/[1-9]\d{6,10}|' \
  1110. '0[1-9]\d{1,2}[-—-―]\d{7,8}.?转\d{1,4}|' \
  1111. '0[1-9]\d{1,2}[-—-―]\d{7,8}[-—-―]\d{1,4}|' \
  1112. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=1[3-9]\d{9})|' \
  1113. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?)|' \
  1114. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=[1-9]\d{6,7})|' \
  1115. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?|' \
  1116. '[\(|\(]0[1-9]\d{1,2}[\)|\)]-?\d{7,8}-?\d{,4}|' \
  1117. '[2-9]\d{6,7})'
  1118. re_tenderee_phone = re.compile(
  1119. "(?:(?:(?:采购|招标|议价|议标|比选)(?:人|公司|单位|组织|部门)|建设(?:单位|业主)|(?:采购|招标|甲)方|询价单位|项目业主|业主)[^。]{0,5}(?:电话|联系方式|联系人|联系电话)[::]?[^。]{0,7}?)"
  1120. # 电话号码
  1121. + phone_pattern)
  1122. # 例:"采购人地址和联系方式:峨边彝族自治县教育局,0833-5226788,"
  1123. re_tenderee_phone2 = re.compile(
  1124. "(?:(?:(?:采购|招标|议价|议标|比选)(?:人|公司|单位|组织|部门)|建设(?:单位|业主)|(?:采购|招标|甲)方|询价单位|项目业主|业主)[^。]{0,3}(?:地址)[^。]{0,3}(?:电话|联系方式|联系人|联系电话)[::]?[^。]{0,20}?)"
  1125. # 电话号码
  1126. + phone_pattern)
  1127. re_agent_phone = re.compile(
  1128. "(?:(?:代理(?:人|机构|公司|单位|组织|方)|采购机构|集中采购机构|集采机构|招标机构)[^。]{0,5}(?:电话|联系方式|联系人|联系电话)[::]?[^。]{0,7}?)"
  1129. # 电话号码
  1130. + phone_pattern)
  1131. re_agent_phone2 = re.compile(
  1132. "(?:(?:代理(?:人|机构|公司|单位|组织|方)|采购机构|集中采购机构|集采机构|招标机构)[^。]{0,3}(?:地址)[^。]{0,3}(?:电话|联系方式|联系人|联系电话)[::]?[^。]{0,20}?)"
  1133. # 电话号码
  1134. + phone_pattern)
  1135. content = ""
  1136. for _sentence in list_sentence:
  1137. content += "".join(_sentence.tokens)
  1138. _content = copy.deepcopy(content)
  1139. while re.search("(.)(,)([^0-9])|([^0-9])(,)(.)", content):
  1140. content_words = list(content)
  1141. for i in re.finditer("(.)(,)([^0-9])", content):
  1142. content_words[i.span(2)[0]] = ""
  1143. for i in re.finditer("([^0-9])(,)(.)", content):
  1144. content_words[i.span(2)[0]] = ""
  1145. content = "".join(content_words)
  1146. content = re.sub("[::]|[\((]|[\))]", "", content)
  1147. _tenderee_phone = re.findall(re_tenderee_phone, content)
  1148. # 更新正则确定的角色属性
  1149. for i in range(len(PackDict["Project"]["roleList"])):
  1150. if PackDict["Project"]["roleList"][i].role_name == "tenderee":
  1151. _tenderee_phone = re.findall(re_tenderee_phone, content)
  1152. if _tenderee_phone:
  1153. for _phone in _tenderee_phone:
  1154. _phone = _phone.split("/") # 分割多个号码
  1155. for one_phone in _phone:
  1156. PackDict["Project"]["roleList"][i].linklist.append(("", one_phone))
  1157. tenderee_phone.add(one_phone)
  1158. _tenderee_phone2 = re.findall(re_tenderee_phone2, content)
  1159. if _tenderee_phone2:
  1160. for _phone in _tenderee_phone2:
  1161. _phone = _phone.split("/")
  1162. for one_phone in _phone:
  1163. PackDict["Project"]["roleList"][i].linklist.append(("", one_phone))
  1164. tenderee_phone.add(one_phone)
  1165. if PackDict["Project"]["roleList"][i].role_name == "agency":
  1166. _agent_phone = re.findall(re_agent_phone, content)
  1167. if _agent_phone:
  1168. for _phone in _agent_phone:
  1169. _phone = _phone.split("/")
  1170. for one_phone in _phone:
  1171. PackDict["Project"]["roleList"][i].linklist.append(("", one_phone))
  1172. agency_phone.add(one_phone)
  1173. _agent_phone2 = re.findall(re_agent_phone2, content)
  1174. if _agent_phone2:
  1175. for _phone in _agent_phone2:
  1176. _phone = _phone.split("/")
  1177. for one_phone in _phone:
  1178. PackDict["Project"]["roleList"][i].linklist.append(("", one_phone))
  1179. agency_phone.add(one_phone)
  1180. # 正则提取电话号码实体
  1181. # key_word = re.compile('((?:电话|联系方式|联系人).{0,4}?)([0-1]\d{6,11})')
  1182. phone = re.compile('1[3-9][0-9][-—-―]?\d{4}[-—-―]?\d{4}|'
  1183. '\+86.?1[3-9]\d{9}|'
  1184. # '0[^0]\d{1,2}[-—-―][1-9]\d{6,7}/[1-9]\d{6,10}|'
  1185. '0[1-9]\d{1,2}[-—-―]\d{7,8}.?转\d{1,4}|'
  1186. '0[1-9]\d{1,2}[-—-―]\d{7,8}[-—-―]\d{1,4}|'
  1187. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=1[3-9]\d{9})|'
  1188. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?)|'
  1189. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=[1-9]\d{6,7})|'
  1190. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?|'
  1191. '[\(|\(]0[1-9]\d{1,2}[\)|\)]-?\d{7,8}-?\d{,4}|'
  1192. '[2-9]\d{6,7}')
  1193. url_pattern = re.compile("http[s]?://(?:[a-zA-Z]|[0-9]|[$\-_@.&+=\?:/]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")
  1194. email_pattern = re.compile("[a-zA-Z0-9][a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*@"
  1195. "[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*(?:\.[a-zA-Z]{2,})")
  1196. phone_entitys = []
  1197. code_entitys = [ent for ent in list_entity if ent.entity_type=='code']
  1198. for _sentence in list_sentence:
  1199. sentence_text = _sentence.sentence_text
  1200. in_attachment = _sentence.in_attachment
  1201. list_tokenbegin = []
  1202. begin = 0
  1203. for i in range(0, len(_sentence.tokens)):
  1204. list_tokenbegin.append(begin)
  1205. begin += len(str(_sentence.tokens[i]))
  1206. list_tokenbegin.append(begin + 1)
  1207. # 排除网址、邮箱、项目编号实体
  1208. error_list = []
  1209. for i in re.finditer(url_pattern, sentence_text):
  1210. error_list.append((i.start(), i.end()))
  1211. for i in re.finditer(email_pattern, sentence_text):
  1212. error_list.append((i.start(), i.end()))
  1213. for code_ent in [ent for ent in code_entitys if ent.sentence_index==_sentence.sentence_index]:
  1214. error_list.append((code_ent.wordOffset_begin,code_ent.wordOffset_end))
  1215. res_set = set()
  1216. for i in re.finditer(phone, sentence_text):
  1217. is_continue = False
  1218. for error_ent in error_list:
  1219. if i.start()>=error_ent[0] and i.end()<=error_ent[1]:
  1220. is_continue = True
  1221. break
  1222. if is_continue:
  1223. continue
  1224. res_set.add((i.group(), i.start(), i.end()))
  1225. res_set = sorted(list(res_set),key=lambda x:x[1])
  1226. last_phone_mask = True
  1227. for item_idx in range(len(res_set)):
  1228. item = res_set[item_idx]
  1229. phone_left = sentence_text[max(0, item[1] - 10):item[1]]
  1230. phone_right = sentence_text[item[2]:item[2] + 8]
  1231. if re.search("电话|手机|联系人|联系方式”",re.sub(",","",phone_left)):
  1232. pass
  1233. else:
  1234. # 排除“传真号”和其它错误项
  1235. if re.search("传,?真|信,?箱|邮,?[箱件]|QQ|qq", phone_left):
  1236. if not re.search("电,?话", phone_left):
  1237. last_phone_mask = False
  1238. continue
  1239. if re.search("注册[证号]|帐号|编[号码]|报价|标价|证号|价格|型号|附件|代码|列号|行号|税号|[\(\(]万?元[\)\)]|[a-zA-Z]+\d*$", re.sub(",","",phone_left)):
  1240. last_phone_mask = False
  1241. continue
  1242. if re.search("^\d{0,4}[.,]\d{2,}|^[0-9a-zA-Z\.]*@|^\d*[a-zA-Z]+|元", phone_right):
  1243. last_phone_mask = False
  1244. continue
  1245. # 前后跟着字母
  1246. if re.search("[a-zA-Z/]+$", phone_left) or re.search("^[a-zA-Z/]+", phone_right):
  1247. last_phone_mask = False
  1248. continue
  1249. # 前后跟着长度小于一定值数字的正则排除
  1250. if re.search("\d+[-—-―]?\d*$",phone_left) or re.search("^\d+[-—-―]?\d*",phone_right):
  1251. phone_left_number = re.search("\d+[-—-―]?\d*$",phone_left)
  1252. phone_right_number = re.search("^\d+[-—-―]?\d+",phone_right)
  1253. if phone_left_number:
  1254. if len(phone_left_number.group())<7:
  1255. last_phone_mask = False
  1256. continue
  1257. if phone_right_number:
  1258. if len(phone_right_number.group())<7:
  1259. last_phone_mask = False
  1260. continue
  1261. # if:上一个phone实体不符合条件
  1262. if not last_phone_mask:
  1263. item_start = item[1]
  1264. last_item_end = res_set[item_idx-1][2]
  1265. if item_start - last_item_end<=1 or re.search("^[\da-zA-Z\-—-―、]+$",sentence_text[last_item_end:item_start]):
  1266. last_phone_mask = False
  1267. continue
  1268. for j in range(len(list_tokenbegin)):
  1269. if list_tokenbegin[j] == item[1]:
  1270. begin_index = j
  1271. break
  1272. elif list_tokenbegin[j] > item[1]:
  1273. begin_index = j - 1
  1274. break
  1275. for j in range(begin_index, len(list_tokenbegin)):
  1276. if list_tokenbegin[j] >= item[2]:
  1277. end_index = j - 1
  1278. break
  1279. _entity = Entity(_sentence.doc_id, None, item[0], "phone", _sentence.sentence_index, begin_index, end_index, item[1],
  1280. item[2],in_attachment=in_attachment)
  1281. phone_entitys.append(_entity)
  1282. last_phone_mask = True
  1283. def is_company(entity,text):
  1284. # 判断"公司"实体是否为地址地点
  1285. if entity.label!=5 and entity.values[entity.label]>0.5:
  1286. return True
  1287. if ent.is_tail==True:
  1288. return False
  1289. entity_left = text[max(0,entity.wordOffset_begin-10):entity.wordOffset_begin]
  1290. entity_left = re.sub(",()\(\)","",entity_left)
  1291. entity_left = entity_left[-5:]
  1292. if re.search("地址|地点|银行[::]",entity_left):
  1293. return False
  1294. else:
  1295. return True
  1296. pre_entity = []
  1297. for ent in list_entity:
  1298. if (ent.entity_type in ['company','org','phone'] and is_company(ent,list_sentence[ent.sentence_index].sentence_text)) or (ent.entity_type=='person' and ent.label in [1,2,3]) \
  1299. or (ent.entity_type=='location' and len(ent.entity_text)>5):
  1300. pre_entity.append(ent)
  1301. text_data,pre_data = relationExtraction_model.encode(pre_entity + phone_entitys, list_sentence)
  1302. # print(pre_data)
  1303. maxlen = 512
  1304. relation_list = []
  1305. if 0<len(text_data)<=maxlen:
  1306. relation_list = relationExtraction_model.predict(text_data, pre_data)
  1307. else:
  1308. # 公告大于maxlen时,分段预测
  1309. start = 0
  1310. # print("len(pre_data)",len(pre_data))
  1311. temp_data = []
  1312. deal_data = 0
  1313. while start<len(pre_data):
  1314. _pre_data = pre_data[start:start+maxlen]
  1315. _text_data = text_data[start:start+maxlen]
  1316. if relationExtraction_model.check_data(_pre_data):
  1317. temp_data.append((_text_data,_pre_data))
  1318. else:
  1319. if temp_data:
  1320. deal_data += len(temp_data)
  1321. if deal_data>3:
  1322. break
  1323. for _text_data, _pre_data in temp_data:
  1324. relation_list.extend(relationExtraction_model.predict(_text_data,_pre_data))
  1325. temp_data = []
  1326. start = start + maxlen - 120
  1327. # print("预测数据:",len(temp_data))
  1328. # if len(temp_data)<=6:
  1329. # for _text_data,_pre_data in temp_data:
  1330. # relation_list.extend(relationExtraction_model.predict(_text_data,_pre_data))
  1331. # else:
  1332. # relation_list = []
  1333. # 去重结果
  1334. relation_list = list(set(relation_list))
  1335. # print(relation_list)
  1336. # tokens_num_dict = dict()
  1337. # last_tokens_num = 0
  1338. # for sentence in list_sentence:
  1339. # _index = sentence.sentence_index
  1340. # if _index == 0:
  1341. # tokens_num_dict[_index] = 0
  1342. # else:
  1343. # tokens_num_dict[_index] = tokens_num_dict[_index - 1] + last_tokens_num
  1344. # last_tokens_num = len(sentence.tokens)
  1345. right_combination = [('org','person'),('company','person'),('company','location'),('org','location'),('person','phone')]
  1346. linked_company = set()
  1347. linked_person = set()
  1348. linked_connetPerson = set()
  1349. linked_phone = set()
  1350. for predicate in ["rel_address","rel_phone","rel_person"]:
  1351. _match_list = []
  1352. _match_combo = []
  1353. for relation in relation_list:
  1354. _subject = relation[0]
  1355. _object = relation[2]
  1356. if isinstance(_subject,Entity) and isinstance(_object,Entity) and (_subject.entity_type,_object.entity_type) in right_combination:
  1357. if relation[1]==predicate:
  1358. if predicate=="rel_person":
  1359. if (_subject.label==0 and _object.entity_text in agency_contact ) or (_subject.label==1 and _object.entity_text in tenderee_contact):
  1360. continue
  1361. distance = (tokens_num_dict[_object.sentence_index] + _object.begin_index) - (
  1362. tokens_num_dict[_subject.sentence_index] + _subject.end_index)
  1363. if distance>0:
  1364. value = (-1 / 2 * (distance ** 2))/10000
  1365. else:
  1366. distance = abs(distance)
  1367. value = (-1 / 2 * (distance ** 2))
  1368. _match_list.append(Match(_subject,_object,value))
  1369. _match_combo.append((_subject,_object))
  1370. match_result = dispatch(_match_list)
  1371. error_list = []
  1372. for mat in list(set(_match_combo)-set(match_result)):
  1373. for temp in match_result:
  1374. if mat[1]==temp[1] and mat[0]!=temp[0]:
  1375. error_list.append(mat)
  1376. break
  1377. result = list(set(_match_combo)-set(error_list))
  1378. if predicate=='rel_person':
  1379. # 从后往前更新状态,已近后向链接的属性不在前向链接(解决错误链接)
  1380. result = sorted(result,key=lambda x:x[1].begin_index,reverse=True)
  1381. for combo in result:
  1382. is_continue = False
  1383. if not combo[0].pointer_person:
  1384. combo[0].pointer_person = []
  1385. if combo[1].begin_index<combo[0].begin_index:
  1386. if combo[0].pointer_person:
  1387. for temp in combo[0].pointer_person:
  1388. if temp.begin_index>combo[0].begin_index:
  1389. is_continue = True
  1390. break
  1391. if is_continue: continue
  1392. combo[0].pointer_person.append(combo[1])
  1393. linked_company.add(combo[0])
  1394. linked_person.add(combo[1])
  1395. # print(1,combo[0].entity_text,combo[1].entity_text)
  1396. if predicate=='rel_address':
  1397. result = sorted(result,key=lambda x:x[1].begin_index,reverse=True)
  1398. for combo in result:
  1399. if combo[0].pointer_address:
  1400. continue
  1401. combo[0].pointer_address = combo[1]
  1402. # print(2,combo[0].entity_text,combo[1].entity_text)
  1403. if predicate=='rel_phone':
  1404. result = sorted(result,key=lambda x:x[1].begin_index,reverse=True)
  1405. for combo in result:
  1406. is_continue = False
  1407. if not combo[0].person_phone:
  1408. combo[0].person_phone = []
  1409. if combo[1].begin_index<combo[0].begin_index:
  1410. if combo[0].person_phone:
  1411. for temp in combo[0].person_phone:
  1412. if temp.begin_index>combo[0].begin_index:
  1413. is_continue = True
  1414. break
  1415. if is_continue: continue
  1416. combo[0].person_phone.append(combo[1])
  1417. linked_connetPerson.add(combo[0])
  1418. linked_phone.add(combo[1])
  1419. if combo[0].label in [1,2]:
  1420. if PackDict.get("Project"):
  1421. for i in range(len(PackDict["Project"]["roleList"])):
  1422. if (combo[0].label==1 and PackDict["Project"]["roleList"][i].role_name=='tenderee') \
  1423. or (combo[0].label==2 and PackDict["Project"]["roleList"][i].role_name=='agency'):
  1424. PackDict["Project"]["roleList"][i].linklist.append((combo[0].entity_text,combo[1].entity_text))
  1425. break
  1426. # print(3,combo[0].entity_text,combo[1].entity_text)
  1427. # "联系人——联系电话" 链接规则补充
  1428. person_phone_EntityList = [ent for ent in pre_entity+ phone_entitys if ent.entity_type not in ['company','org','location']]
  1429. person_phone_EntityList = sorted(person_phone_EntityList, key=lambda x: (x.sentence_index, x.begin_index))
  1430. t_match_list = []
  1431. for ent_idx in range(len(person_phone_EntityList)):
  1432. entity = person_phone_EntityList[ent_idx]
  1433. if entity.entity_type=="person":
  1434. match_nums = 0
  1435. person_nums = 0 # 经过其他中联系人的数量
  1436. byNotPerson_match_nums = 0 # 跟在联系人后面的属性
  1437. phone_nums = 0 # 经过电话的数量
  1438. for after_index in range(ent_idx + 1, min(len(person_phone_EntityList), ent_idx + 8)):
  1439. after_entity = person_phone_EntityList[after_index]
  1440. if after_entity.entity_type == "phone":
  1441. distance = (tokens_num_dict[after_entity.sentence_index] + after_entity.begin_index) - (
  1442. tokens_num_dict[entity.sentence_index] + entity.end_index)
  1443. phone_nums += 1
  1444. if distance>100 or phone_nums>=4:
  1445. break
  1446. sentence_distance = after_entity.sentence_index - entity.sentence_index
  1447. value = (-1 / 2 * (distance ** 2)) / 10000
  1448. if sentence_distance == 0:
  1449. if distance < 80:
  1450. # value = (-1 / 2 * (distance ** 2)) / 10000
  1451. t_match_list.append(Match(entity, after_entity, value))
  1452. match_nums += 1
  1453. if not person_nums:
  1454. byNotPerson_match_nums += 1
  1455. else:
  1456. break
  1457. else:
  1458. if distance < 50:
  1459. # value = (-1 / 2 * (distance ** 2)) / 10000
  1460. t_match_list.append(Match(entity, after_entity, value))
  1461. match_nums += 1
  1462. if not person_nums:
  1463. byNotPerson_match_nums += 1
  1464. else:
  1465. break
  1466. else:
  1467. person_nums += 1
  1468. # 前向查找属性
  1469. if ent_idx != 0 and (not match_nums or not byNotPerson_match_nums):
  1470. previous_entity = person_phone_EntityList[ent_idx - 1]
  1471. if previous_entity.entity_type == 'phone':
  1472. # if previous_entity.sentence_index == entity.sentence_index:
  1473. distance = (tokens_num_dict[entity.sentence_index] + entity.begin_index) - (
  1474. tokens_num_dict[previous_entity.sentence_index] + previous_entity.end_index)
  1475. if distance < 40:
  1476. # 前向 没有 /10000
  1477. value = (-1 / 2 * (distance ** 2))
  1478. t_match_list.append(Match(entity, previous_entity, value))
  1479. # km算法分配求解(person-phone)
  1480. t_match_list = [mat for mat in t_match_list if mat.main_role not in linked_connetPerson and mat.attribute not in linked_phone]
  1481. personphone_result = dispatch(t_match_list)
  1482. personphone_result = sorted(personphone_result, key=lambda x: (x[0].sentence_index, x[0].begin_index))
  1483. for match in personphone_result:
  1484. _person = match[0]
  1485. _phone = match[1]
  1486. if not _person.person_phone:
  1487. _person.person_phone = []
  1488. _person.person_phone.append(_phone)
  1489. # 多个招标人/代理人或者别称
  1490. for idx in range(1,len(pre_entity)):
  1491. _pre_entity = pre_entity[idx]
  1492. if _pre_entity in linked_company and _pre_entity.label==5:
  1493. last_ent = pre_entity[idx-1]
  1494. if last_ent.entity_type in ['company','org'] and last_ent.label in [0,1]:
  1495. if last_ent.sentence_index==_pre_entity.sentence_index:
  1496. mid_text = list_sentence[_pre_entity.sentence_index].sentence_text[last_ent.wordOffset_end:_pre_entity.wordOffset_begin]
  1497. if len(mid_text)<=20 and "," not in mid_text and re.search("[、\((]",mid_text):
  1498. _pre_entity.label = last_ent.label
  1499. _pre_entity.values[last_ent.label] = 0.6
  1500. # 2022/01/25 固定电话可连多个联系人
  1501. temp_person_entitys = [entity for entity in pre_entity if entity.entity_type == 'person']
  1502. temp_person_entitys2 = [] #和固定电话相连的联系人
  1503. for entity in temp_person_entitys:
  1504. if entity.person_phone:
  1505. for _phone in entity.person_phone:
  1506. if not re.search("^1[3-9]\d{9}$", _phone.entity_text):
  1507. temp_person_entitys2.append(entity)
  1508. break
  1509. for index in range(len(temp_person_entitys)):
  1510. entity = temp_person_entitys[index]
  1511. if entity in temp_person_entitys2:
  1512. last_person = entity
  1513. for after_index in range(index + 1, min(len(temp_person_entitys), index + 5)):
  1514. after_entity = temp_person_entitys[after_index]
  1515. if after_entity.sentence_index == last_person.sentence_index and after_entity.begin_index - last_person.end_index < 3:
  1516. for _phone in entity.person_phone:
  1517. if not re.search("^1[3-9]\d{9}$", _phone.entity_text):
  1518. if _phone not in after_entity.person_phone:
  1519. after_entity.person_phone.append(_phone)
  1520. last_person = after_entity
  1521. else:
  1522. break
  1523. if index==0:
  1524. continue
  1525. last_person = entity
  1526. for before_index in range(index-1, max(-1,index-5), -1):
  1527. before_entity = temp_person_entitys[before_index]
  1528. if before_entity.sentence_index == last_person.sentence_index and last_person.begin_index - before_entity.end_index < 3:
  1529. for _phone in entity.person_phone:
  1530. if not re.search("^1[3-9]\d{9}$", _phone.entity_text):
  1531. if _phone not in before_entity.person_phone:
  1532. before_entity.person_phone.append(_phone)
  1533. last_person = before_entity
  1534. else:
  1535. break
  1536. # 更新person为招标/代理联系人的联系方式
  1537. for k in PackDict.keys():
  1538. for i in range(len(PackDict[k]["roleList"])):
  1539. if PackDict[k]["roleList"][i].role_name == "tenderee":
  1540. for _person in person_list:
  1541. if _person.label==1:#招标联系人
  1542. person_phone = [phone for phone in _person.person_phone] if _person.person_phone else []
  1543. for _p in person_phone:
  1544. PackDict[k]["roleList"][i].linklist.append((_person.entity_text, _p.entity_text))
  1545. if not person_phone:
  1546. PackDict[k]["roleList"][i].linklist.append((_person.entity_text,""))
  1547. if PackDict[k]["roleList"][i].role_name == "agency":
  1548. for _person in person_list:
  1549. if _person.label==2:#代理联系人
  1550. person_phone = [phone for phone in _person.person_phone] if _person.person_phone else []
  1551. for _p in person_phone:
  1552. PackDict[k]["roleList"][i].linklist.append((_person.entity_text, _p.entity_text))
  1553. if not person_phone:
  1554. PackDict[k]["roleList"][i].linklist.append((_person.entity_text,""))
  1555. # 更新 PackDict
  1556. not_sure_linked = []
  1557. for link_p in list(linked_company):
  1558. for k in PackDict.keys():
  1559. for i in range(len(PackDict[k]["roleList"])):
  1560. if PackDict[k]["roleList"][i].role_name == "tenderee":
  1561. if PackDict[k]["roleList"][i].entity_text != link_p.entity_text and link_p.label == 0:
  1562. not_sure_linked.append(link_p)
  1563. continue
  1564. if PackDict[k]["roleList"][i].entity_text == link_p.entity_text:
  1565. for per in link_p.pointer_person:
  1566. person_phone = [phone for phone in per.person_phone] if per.person_phone else []
  1567. if not person_phone:
  1568. if per.entity_text not in agency_contact:
  1569. PackDict[k]["roleList"][i].linklist.append((per.entity_text, ""))
  1570. continue
  1571. for _p in person_phone:
  1572. if per.entity_text not in agency_contact and _p.entity_text not in agency_phone:
  1573. PackDict[k]["roleList"][i].linklist.append((per.entity_text, _p.entity_text))
  1574. elif PackDict[k]["roleList"][i].role_name == "agency":
  1575. if PackDict[k]["roleList"][i].entity_text != link_p.entity_text and link_p.label == 1:
  1576. not_sure_linked.append(link_p)
  1577. continue
  1578. if PackDict[k]["roleList"][i].entity_text == link_p.entity_text:
  1579. for per in link_p.pointer_person:
  1580. person_phone = [phone for phone in per.person_phone] if per.person_phone else []
  1581. if not person_phone:
  1582. if per.entity_text not in tenderee_contact:
  1583. PackDict[k]["roleList"][i].linklist.append((per.entity_text, ""))
  1584. continue
  1585. for _p in person_phone:
  1586. if per.entity_text not in tenderee_contact and _p.entity_text not in tenderee_phone:
  1587. PackDict[k]["roleList"][i].linklist.append((per.entity_text, _p.entity_text))
  1588. else:
  1589. if PackDict[k]["roleList"][i].entity_text == link_p.entity_text:
  1590. for per in link_p.pointer_person:
  1591. person_phone = [phone for phone in per.person_phone] if per.person_phone else []
  1592. if not person_phone:
  1593. if per.entity_text not in tenderee_contact and per.entity_text not in agency_contact:
  1594. PackDict[k]["roleList"][i].linklist.append((per.entity_text, ""))
  1595. winter_contact.add(per.entity_text)
  1596. continue
  1597. for _p in person_phone:
  1598. if per.entity_text not in tenderee_contact and _p.entity_text not in tenderee_phone and \
  1599. per.entity_text not in agency_contact and _p.entity_text not in agency_phone:
  1600. PackDict[k]["roleList"][i].linklist.append((per.entity_text, _p.entity_text))
  1601. winter_contact.add(per.entity_text)
  1602. # 更新org/company实体label为0,1的链接
  1603. for link_p in not_sure_linked:
  1604. for k in PackDict.keys():
  1605. for i in range(len(PackDict[k]["roleList"])):
  1606. if PackDict[k]["roleList"][i].role_name == "tenderee":
  1607. if link_p.label == 0:
  1608. for per in link_p.pointer_person:
  1609. person_phone = [phone for phone in per.person_phone] if per.person_phone else []
  1610. if not person_phone:
  1611. if per.entity_text not in agency_contact and per.entity_text not in winter_contact:
  1612. PackDict[k]["roleList"][i].linklist.append((per.entity_text, ""))
  1613. continue
  1614. for _p in person_phone:
  1615. if per.entity_text not in agency_contact and _p.entity_text not in agency_phone and per.entity_text not in winter_contact:
  1616. PackDict[k]["roleList"][i].linklist.append((per.entity_text, _p.entity_text))
  1617. elif PackDict[k]["roleList"][i].role_name == "agency":
  1618. if link_p.label == 1:
  1619. for per in link_p.pointer_person:
  1620. person_phone = [phone for phone in per.person_phone] if per.person_phone else []
  1621. if not person_phone:
  1622. if per.entity_text not in tenderee_contact and per.entity_text not in winter_contact:
  1623. PackDict[k]["roleList"][i].linklist.append((per.entity_text, ""))
  1624. continue
  1625. for _p in person_phone:
  1626. if per.entity_text not in tenderee_contact and _p.entity_text not in tenderee_phone and per.entity_text not in winter_contact:
  1627. PackDict[k]["roleList"][i].linklist.append((per.entity_text, _p.entity_text))
  1628. re_split = re.compile("[^\u4e00-\u9fa5、](十一|十二|十三|十四|十五|一|二|三|四|五|六|七|八|九|十)、")
  1629. split_list = [0] * 16
  1630. split_dict = {
  1631. "一、": 1,
  1632. "二、": 2,
  1633. "三、": 3,
  1634. "四、": 4,
  1635. "五、": 5,
  1636. "六、": 6,
  1637. "七、": 7,
  1638. "八、": 8,
  1639. "九、": 9,
  1640. "十、": 10,
  1641. "十一、": 11,
  1642. "十二、": 12,
  1643. "十三、": 13,
  1644. "十四、": 14,
  1645. "十五、": 15
  1646. }
  1647. for item in re.finditer(re_split, _content):
  1648. _index = split_dict.get(item.group()[1:])
  1649. if not split_list[_index]:
  1650. split_list[_index] = item.span()[0] + 1
  1651. split_list = [i for i in split_list if i != 0]
  1652. start = 0
  1653. new_split_list = []
  1654. for idx in split_list:
  1655. new_split_list.append((start, idx))
  1656. start = idx
  1657. new_split_list.append((start, len(_content)))
  1658. # 实体列表按照“公告分段”分组
  1659. words_num_dict = dict()
  1660. last_words_num = 0
  1661. for sentence in list_sentence:
  1662. _index = sentence.sentence_index
  1663. if _index == 0:
  1664. words_num_dict[_index] = 0
  1665. else:
  1666. words_num_dict[_index] = words_num_dict[_index - 1] + last_words_num
  1667. last_words_num = len(sentence.sentence_text)
  1668. # 公司-联系人连接(km算法)
  1669. re_phone = re.compile('1[3-9][0-9][-—-―]?\d{4}[-—-―]?\d{4}|'
  1670. '\+86.?1[3-9]\d{9}|'
  1671. '0[1-9]\d{1,2}[-—-―][1-9]\d{6,7}/[1-9]\d{6,10}|'
  1672. '0[1-9]\d{1,2}[-—-―]\d{7,8}.?转\d{1,4}|'
  1673. '0[1-9]\d{1,2}[-—-―]\d{7,8}[-—-―]\d{1,4}|'
  1674. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=1[3-9]\d{9})|'
  1675. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?)|'
  1676. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?(?=[1-9]\d{6,7})|'
  1677. '0[1-9]\d{1,2}[-—-―]?[1-9]\d{6}\d?|'
  1678. '[\(|\(]0[1-9]\d{1,2}[\)|\)]-?\d{7,8}-?\d{,4}|'
  1679. '[2-9]\d{6,7}')
  1680. key_phone = re.compile("联系方式|电话|联系人|负责人")
  1681. temporary_list2 = []
  1682. for entity in list_entity:
  1683. # if entity.entity_type in ['org', 'company', 'person'] and entity.is_tail==False:
  1684. if entity.entity_type in ['org', 'company', 'person']:
  1685. temporary_list2.append(entity)
  1686. temporary_list2 = sorted(temporary_list2, key=lambda x: (x.sentence_index, x.begin_index))
  1687. new_temporary_list2 = []
  1688. for _split in new_split_list:
  1689. temp_list = []
  1690. for _entity in temporary_list2:
  1691. if words_num_dict[_entity.sentence_index] + _entity.wordOffset_begin >= _split[0] and words_num_dict[
  1692. _entity.sentence_index] + _entity.wordOffset_end < _split[1]:
  1693. temp_list.append(_entity)
  1694. elif words_num_dict[_entity.sentence_index] + _entity.wordOffset_begin >= _split[1]:
  1695. break
  1696. new_temporary_list2.append(temp_list)
  1697. # print(new_temporary_list2)
  1698. match_list2 = []
  1699. for split_index in range(len(new_temporary_list2)):
  1700. split_entitys = new_temporary_list2[split_index]
  1701. is_skip = False
  1702. for index in range(len(split_entitys)):
  1703. entity = split_entitys[index]
  1704. if is_skip:
  1705. is_skip = False
  1706. continue
  1707. else:
  1708. if entity.entity_type in ['org', 'company']:
  1709. if entity.label != 5 or entity.entity_text in roleSet:
  1710. match_nums = 0
  1711. for after_index in range(index + 1, min(len(split_entitys), index + 4)):
  1712. after_entity = split_entitys[after_index]
  1713. if after_entity.entity_type in ['person']:
  1714. # 实体为中标人/候选人,联系人已确定类别【1,2】
  1715. if entity.label in [2, 3, 4] and after_entity.label in [1, 2]:
  1716. break
  1717. if after_entity.label in [1, 2, 3]:
  1718. distance = (tokens_num_dict[
  1719. after_entity.sentence_index] + after_entity.begin_index) - (
  1720. tokens_num_dict[entity.sentence_index] + entity.end_index)
  1721. sentence_distance = after_entity.sentence_index - entity.sentence_index
  1722. if sentence_distance == 0:
  1723. if distance < 100:
  1724. if (entity.label == 0 and after_entity.label == 1) or (
  1725. entity.label == 1 and after_entity.label == 2):
  1726. distance = distance / 100
  1727. value = (-1 / 2 * (distance ** 2)) / 10000
  1728. match_list2.append(Match(entity, after_entity, value))
  1729. match_nums += 1
  1730. else:
  1731. if distance < 60:
  1732. if (entity.label == 0 and after_entity.label == 1) or (
  1733. entity.label == 1 and after_entity.label == 2):
  1734. distance = distance / 100
  1735. value = (-1 / 2 * (distance ** 2)) / 10000
  1736. match_list2.append(Match(entity, after_entity, value))
  1737. match_nums += 1
  1738. if after_entity.entity_type in ['org', 'company']:
  1739. # 解决在‘地址’中识别出org/company的问题
  1740. # if entity.label in [0,1] and after_index==index+1 and after_entity.label not in [0,1]:
  1741. if entity.label != 5 and after_index == index + 1 and (
  1742. after_entity.label == entity.label or after_entity.label == 5):
  1743. distance = (tokens_num_dict[
  1744. after_entity.sentence_index] + after_entity.begin_index) - (
  1745. tokens_num_dict[entity.sentence_index] + entity.end_index)
  1746. if distance < 20:
  1747. after_entity_left = list_sentence[after_entity.sentence_index].tokens[max(0,
  1748. after_entity.begin_index - 10):after_entity.begin_index]
  1749. after_entity_right = list_sentence[after_entity.sentence_index].tokens[
  1750. after_entity.end_index + 1:after_entity.end_index + 6]
  1751. after_entity_left = "".join(after_entity_left)
  1752. if len(after_entity_left) > 20:
  1753. after_entity_left = after_entity_left[-20:]
  1754. after_entity_right = "".join(after_entity_right)[:10]
  1755. if re.search("地,?址", after_entity_left):
  1756. is_skip = True
  1757. continue
  1758. if re.search("\(|(", after_entity_left) and re.search("\)|)",
  1759. after_entity_right):
  1760. is_skip = True
  1761. continue
  1762. if entity.label in [0, 1] and after_entity.label in [0,
  1763. 1] and entity.label == after_entity.label:
  1764. break
  1765. if entity.label in [0, 1] and after_entity.label in [0, 1] and split_entitys[
  1766. index + 1].entity_type == "person":
  1767. break
  1768. if entity.label in [0, 1] and after_entity.label in [2, 3, 4]:
  1769. break
  1770. if entity.label in [2, 3, 4] and after_entity.label in [0, 1]:
  1771. break
  1772. # 搜索没有联系人的电话
  1773. mid_tokens = []
  1774. is_same_sentence = False
  1775. if index == len(split_entitys) - 1:
  1776. for i in range(entity.sentence_index, len(list_sentence)):
  1777. mid_tokens += list_sentence[i].tokens
  1778. mid_tokens = mid_tokens[entity.end_index + 1:]
  1779. mid_sentence = "".join(mid_tokens)
  1780. have_phone = re.findall(re_phone, mid_sentence)
  1781. if have_phone:
  1782. if re.findall(re_phone, mid_sentence.split("。")[0]):
  1783. is_same_sentence = True
  1784. _phone = have_phone[0]
  1785. phone_begin = mid_sentence.find(_phone)
  1786. if words_num_dict[entity.sentence_index] + entity.wordOffset_begin + phone_begin < \
  1787. new_split_list[split_index][1]:
  1788. mid_sentence = mid_sentence[max(0, phone_begin - 15):phone_begin].replace(",", "")
  1789. if re.search(key_phone, mid_sentence):
  1790. distance = 1
  1791. if is_same_sentence:
  1792. if phone_begin <= 200:
  1793. value = (-1 / 2 * (distance ** 2)) / 10000
  1794. match_list2.append(Match(entity, (entity, _phone), value))
  1795. match_nums += 1
  1796. else:
  1797. if phone_begin <= 60:
  1798. value = (-1 / 2 * (distance ** 2)) / 10000
  1799. match_list2.append(Match(entity, (entity, _phone), value))
  1800. match_nums += 1
  1801. else:
  1802. next_entity = split_entitys[index + 1]
  1803. if next_entity.entity_type in ["org","company"]:
  1804. _entity_left = list_sentence[next_entity.sentence_index].sentence_text[max(0, next_entity.wordOffset_begin - 20):next_entity.wordOffset_begin]
  1805. _entity_left2 = re.sub(",()\(\)::", "", _entity_left)
  1806. _entity_left2 = _entity_left2[-5:]
  1807. if re.search("(地,?址|地,?点)[::][^,。]*$", _entity_left) or re.search("地址|地点", _entity_left2):
  1808. if index + 2<= len(split_entitys) - 1:
  1809. next_entity = split_entitys[index + 2]
  1810. if entity.sentence_index == next_entity.sentence_index:
  1811. mid_tokens += list_sentence[entity.sentence_index].tokens[
  1812. entity.end_index + 1:next_entity.begin_index]
  1813. else:
  1814. sentence_index = entity.sentence_index
  1815. while sentence_index <= next_entity.sentence_index:
  1816. mid_tokens += list_sentence[sentence_index].tokens
  1817. sentence_index += 1
  1818. mid_tokens = mid_tokens[entity.end_index + 1:-(len(
  1819. list_sentence[next_entity.sentence_index].tokens) - next_entity.begin_index) + 1]
  1820. mid_sentence = "".join(mid_tokens)
  1821. have_phone = re.findall(re_phone, mid_sentence)
  1822. if have_phone:
  1823. if re.findall(re_phone, mid_sentence.split("。")[0]):
  1824. is_same_sentence = True
  1825. _phone = have_phone[0]
  1826. phone_begin = mid_sentence.find(_phone)
  1827. mid_sentence = mid_sentence[max(0, phone_begin - 15):phone_begin].replace(",", "")
  1828. if re.search(key_phone, mid_sentence):
  1829. p_phone = [p.entity_text for p in next_entity.person_phone] if next_entity.person_phone else []
  1830. if next_entity.entity_type == 'person' and _phone in p_phone:
  1831. pass
  1832. else:
  1833. distance = (tokens_num_dict[
  1834. next_entity.sentence_index] + next_entity.begin_index) - (
  1835. tokens_num_dict[entity.sentence_index] + entity.end_index)
  1836. distance = distance / 2
  1837. if is_same_sentence:
  1838. if phone_begin <= 200:
  1839. value = (-1 / 2 * (distance ** 2)) / 10000
  1840. match_list2.append(Match(entity, (entity, _phone), value))
  1841. match_nums += 1
  1842. else:
  1843. if phone_begin <= 60:
  1844. value = (-1 / 2 * (distance ** 2)) / 10000
  1845. match_list2.append(Match(entity, (entity, _phone), value))
  1846. match_nums += 1
  1847. # 实体无匹配时,尝试前向查找匹配
  1848. if not match_nums:
  1849. if (entity.label != 5 or entity.entity_text in roleSet) and entity.values[entity.label] >= 0.5 and index != 0:
  1850. previous_entity = split_entitys[index - 1]
  1851. if previous_entity.entity_type == 'person' and previous_entity.label in [1, 2, 3]:
  1852. if entity.label in [2, 3, 4] and previous_entity.label in [1, 2]:
  1853. continue
  1854. if previous_entity.sentence_index == entity.sentence_index:
  1855. distance = (tokens_num_dict[entity.sentence_index] + entity.begin_index) - (
  1856. tokens_num_dict[
  1857. previous_entity.sentence_index] + previous_entity.end_index)
  1858. if distance < 20:
  1859. # 距离相等时,前向添加处罚值
  1860. # distance += 1
  1861. # 前向 没有 /10000
  1862. value = (-1 / 2 * (distance ** 2))
  1863. match_list2.append(Match(entity, previous_entity, value))
  1864. # print(match_list2)
  1865. match_list2 = [mat for mat in match_list2 if mat.main_role not in linked_company and mat.attribute not in linked_person]
  1866. # print(match_list2)
  1867. # km算法分配求解
  1868. result2 = dispatch(match_list2)
  1869. # print(result2)
  1870. for match in result2:
  1871. entity = match[0]
  1872. # print(entity.entity_text)
  1873. # print(match.attribute)
  1874. entity_index = list_entity.index(entity)
  1875. is_update = False
  1876. if isinstance(match[1], tuple):
  1877. person_ = ''
  1878. phone_ = match[1][1].split("/") # 分割多个号码
  1879. # print(person_,phone_)
  1880. else:
  1881. person_ = match[1].entity_text
  1882. phone_ = [i.entity_text for i in match[1].person_phone] if match[1].person_phone else []
  1883. for k in PackDict.keys():
  1884. for i in range(len(PackDict[k]["roleList"])):
  1885. if PackDict[k]["roleList"][i].role_name == "tenderee":
  1886. # if not PackDict[k]["roleList"][i].linklist:
  1887. if PackDict[k]["roleList"][i].entity_text == entity.entity_text or entity.label == 0:
  1888. if person_ not in agency_contact and len(set(phone_)&set(agency_phone))==0 and person_ not in winter_contact:
  1889. if not phone_:
  1890. PackDict[k]["roleList"][i].linklist.append((person_, ""))
  1891. for p in phone_:
  1892. # if not person_ and len()
  1893. PackDict[k]["roleList"][i].linklist.append((person_, p))
  1894. is_update = True
  1895. elif PackDict[k]["roleList"][i].role_name == "agency":
  1896. # if not PackDict[k]["roleList"][i].linklist:
  1897. if PackDict[k]["roleList"][i].entity_text == entity.entity_text or entity.label == 1 and person_ not in winter_contact:
  1898. if person_ not in tenderee_contact and len(set(phone_)&set(tenderee_phone))==0:
  1899. if not phone_:
  1900. PackDict[k]["roleList"][i].linklist.append((person_, ""))
  1901. for p in phone_:
  1902. PackDict[k]["roleList"][i].linklist.append((person_, p))
  1903. is_update = True
  1904. else:
  1905. if PackDict[k]["roleList"][i].entity_text == entity.entity_text:
  1906. if not PackDict[k]["roleList"][i].linklist:
  1907. if person_ not in tenderee_contact and len(set(phone_)&set(tenderee_phone))==0 and \
  1908. person_ not in agency_contact and len(set(phone_)&set(agency_phone))==0:
  1909. if not phone_:
  1910. PackDict[k]["roleList"][i].linklist.append((person_, ""))
  1911. for p in phone_:
  1912. PackDict[k]["roleList"][i].linklist.append((person_, p))
  1913. is_update = True
  1914. if not person_:
  1915. is_update = False
  1916. if is_update:
  1917. # 更新 list_entity
  1918. if not list_entity[entity_index].pointer_person:
  1919. list_entity[entity_index].pointer_person = []
  1920. list_entity[entity_index].pointer_person.append(match[1])
  1921. linked_person = []
  1922. linked_persons_with = []
  1923. for company_entity in [entity for entity in list_entity if entity.entity_type in ['company','org']]:
  1924. if company_entity.pointer_person:
  1925. for _person in company_entity.pointer_person:
  1926. linked_person.append(_person)
  1927. linked_persons_with.append(company_entity)
  1928. # 一个公司对应多个联系人的补充
  1929. person_entitys = [entity for entity in list_entity if entity.entity_type=='person']
  1930. person_entitys = person_entitys[::-1]
  1931. for index in range(len(person_entitys)):
  1932. entity = person_entitys[index]
  1933. prepare_link = []
  1934. if entity not in linked_person:
  1935. prepare_link.append(entity)
  1936. last_person = entity
  1937. for after_index in range(index + 1, min(len(person_entitys), index + 5)):
  1938. after_entity = person_entitys[after_index]
  1939. if after_entity.sentence_index==last_person.sentence_index and last_person.begin_index-after_entity.end_index<5:
  1940. if after_entity in linked_person:
  1941. _index = linked_person.index(after_entity)
  1942. with_company = linked_persons_with[_index]
  1943. for i in range(len(PackDict["Project"]["roleList"])):
  1944. if PackDict["Project"]["roleList"][i].role_name == "tenderee":
  1945. if PackDict["Project"]["roleList"][i].entity_text == with_company.entity_text or with_company.label == 0:
  1946. for item in prepare_link:
  1947. person_phone = [p.entity_text for p in item.person_phone] if item.person_phone else []
  1948. for _p in person_phone:
  1949. PackDict["Project"]["roleList"][i].linklist.append((item.entity_text, _p))
  1950. with_company.pointer_person.append(item)
  1951. linked_person.append(item)
  1952. elif PackDict["Project"]["roleList"][i].role_name == "agency":
  1953. if PackDict["Project"]["roleList"][i].entity_text == with_company.entity_text or with_company.label == 1:
  1954. for item in prepare_link:
  1955. person_phone = [p.entity_text for p in item.person_phone] if item.person_phone else []
  1956. for _p in person_phone:
  1957. PackDict["Project"]["roleList"][i].linklist.append((item.entity_text, _p))
  1958. with_company.pointer_person.append(item)
  1959. linked_person.append(item)
  1960. else:
  1961. if PackDict["Project"]["roleList"][i].entity_text == with_company.entity_text:
  1962. for item in prepare_link:
  1963. person_phone = [p.entity_text for p in item.person_phone] if item.person_phone else []
  1964. for _p in person_phone:
  1965. PackDict["Project"]["roleList"][i].linklist.append((item.entity_text, _p))
  1966. with_company.pointer_person.append(item)
  1967. linked_person.append(item)
  1968. break
  1969. else:
  1970. prepare_link.append(after_entity)
  1971. last_person = after_entity
  1972. continue
  1973. # 统一同类角色的属性
  1974. if PackDict.get("Project"):
  1975. for i in range(len(PackDict["Project"]["roleList"])):
  1976. # if PackDict["Project"]["roleList"][i].role_name in ["tenderee","agency"]:
  1977. for _entity in list_entity:
  1978. if _entity.entity_type in ['org','company']:
  1979. is_similar = False
  1980. # entity_text相同
  1981. if _entity.entity_text==PackDict["Project"]["roleList"][i].entity_text:
  1982. is_similar = True
  1983. # entity.label为【0,1】
  1984. if _entity.label in [0,1] and dict_role_id[str(_entity.label)]==PackDict["Project"]["roleList"][i].role_name:
  1985. is_similar = True
  1986. if is_similar:
  1987. linked_entitys = _entity.linked_entitys
  1988. if linked_entitys:
  1989. for linked_entity in linked_entitys:
  1990. pointer_person = linked_entity.pointer_person if linked_entity.pointer_person else []
  1991. for _pointer_person in pointer_person:
  1992. _phone = [p.entity_text for p in _pointer_person.person_phone] if _pointer_person.person_phone else []
  1993. for _p in _phone:
  1994. if (_pointer_person.entity_text,_p) not in PackDict["Project"]["roleList"][i].linklist:
  1995. PackDict["Project"]["roleList"][i].linklist.append((_pointer_person.entity_text,_p))
  1996. # "roleList"中联系人电话去重
  1997. for i in range(len(PackDict["Project"]["roleList"])):
  1998. # print(123, PackDict["Project"]["roleList"][i].linklist)
  1999. # 带有联系人的电话
  2000. with_person = [person_phone[1] for person_phone in PackDict["Project"]["roleList"][i].linklist if person_phone[0]]
  2001. # 带有电话的联系人
  2002. with_phone = [person_phone[0] for person_phone in PackDict["Project"]["roleList"][i].linklist if person_phone[1]]
  2003. remove_list = []
  2004. for item in PackDict["Project"]["roleList"][i].linklist:
  2005. if not item[0]:
  2006. if item[1] in with_person:
  2007. # 删除重复的无联系人电话
  2008. remove_list.append(item)
  2009. elif not item[1]:
  2010. if item[0] in with_phone:
  2011. remove_list.append(item)
  2012. for _item in remove_list:
  2013. PackDict["Project"]["roleList"][i].linklist.remove(_item)
  2014. # 联系人——电子邮箱链接
  2015. temporary_list3 = [entity for entity in list_entity if entity.entity_type=='email' or (entity.entity_type=='person' and entity.label in [1,2,3])]
  2016. temporary_list3 = sorted(temporary_list3, key=lambda x: (x.sentence_index, x.begin_index))
  2017. new_temporary_list3 = []
  2018. for _split in new_split_list:
  2019. temp_list = []
  2020. for _entity in temporary_list3:
  2021. if words_num_dict[_entity.sentence_index] + _entity.wordOffset_begin >= _split[0] and words_num_dict[
  2022. _entity.sentence_index] + _entity.wordOffset_end < _split[1]:
  2023. temp_list.append(_entity)
  2024. elif words_num_dict[_entity.sentence_index] + _entity.wordOffset_begin >= _split[1]:
  2025. break
  2026. new_temporary_list3.append(temp_list)
  2027. # print(new_temporary_list3)
  2028. match_list3 = []
  2029. for split_index in range(len(new_temporary_list3)):
  2030. split_entitys = new_temporary_list3[split_index]
  2031. for index in range(len(split_entitys)):
  2032. entity = split_entitys[index]
  2033. if entity.entity_type == 'person':
  2034. match_nums = 0
  2035. for after_index in range(index + 1, min(len(split_entitys), index + 4)):
  2036. after_entity = split_entitys[after_index]
  2037. if match_nums > 2:
  2038. break
  2039. if after_entity.entity_type == 'email':
  2040. distance = (tokens_num_dict[after_entity.sentence_index] + after_entity.begin_index) - (
  2041. tokens_num_dict[entity.sentence_index] + entity.end_index)
  2042. sentence_distance = after_entity.sentence_index - entity.sentence_index
  2043. if sentence_distance == 0:
  2044. if distance < 100:
  2045. if (entity.label == 0 and after_entity.label == 1) or (
  2046. entity.label == 1 and after_entity.label == 2):
  2047. distance = distance / 100
  2048. value = (-1 / 2 * (distance ** 2)) / 10000
  2049. match_list3.append(Match(entity, after_entity, value))
  2050. match_nums += 1
  2051. else:
  2052. if distance < 60:
  2053. if (entity.label == 0 and after_entity.label == 1) or (
  2054. entity.label == 1 and after_entity.label == 2):
  2055. distance = distance / 100
  2056. value = (-1 / 2 * (distance ** 2)) / 10000
  2057. match_list3.append(Match(entity, after_entity, value))
  2058. match_nums += 1
  2059. # 前向查找匹配
  2060. # if not match_nums:
  2061. if index != 0:
  2062. previous_entity = split_entitys[index - 1]
  2063. if previous_entity.entity_type == 'email':
  2064. if previous_entity.sentence_index == entity.sentence_index:
  2065. distance = (tokens_num_dict[entity.sentence_index] + entity.begin_index) - (
  2066. tokens_num_dict[
  2067. previous_entity.sentence_index] + previous_entity.end_index)
  2068. if distance < 30:
  2069. # 距离相等时,前向添加处罚值
  2070. # distance += 1
  2071. # 前向 没有 /10000
  2072. value = (-1 / 2 * (distance ** 2))
  2073. match_list3.append(Match(entity, previous_entity, value))
  2074. # print(match_list3)
  2075. # km算法分配求解
  2076. result3 = dispatch(match_list3)
  2077. for match in result3:
  2078. match_person = match[0]
  2079. match_email = match[1]
  2080. match_person.pointer_email = match_email
  2081. # # 1)第一个公司实体的招标人,则看看下一个实体是否为代理人,如果是则联系人错位连接 。2)在同一句中往后找联系人。3)连接不上在整个文章找联系人。
  2082. # temp_ent_list = [] # 临时列表,记录0,1角色及3联系人
  2083. # other_person = [] # 阈值以上的联系人列表
  2084. # link_person = [] # 有电话没联系上角色的person列表
  2085. # other_ent = []
  2086. # link_ent = []
  2087. # found_person = False
  2088. # ent_list = []
  2089. # for entity in list_entity:
  2090. # if entity.entity_type in ['org','company','person']:
  2091. # ent_list.append(entity)
  2092. # # ent_list = [entity for entity in list_entity if entity.entity_type in ['org','company','person']]
  2093. # #for list_index in range(len(ent_list)):
  2094. # #if ent_list[list_index].entity_type in ['org','company'] and ent_list[list_index].label == 0 and list_index+2<len(ent_list) and \
  2095. # #ent_list[list_index+1].entity_type in ['org','company'] and ent_list[list_index+1].label == 1 and ent_list[list_index+2].entity_type in ['person']:
  2096. # #ent_list[list_index+1], ent_list[list_index+2] = ent_list[list_index+2], ent_list[list_index+1]
  2097. # # 2020/11/25增加确定角色联系人判断
  2098. # sure_person_set = set([entity.entity_text for entity in ent_list if entity.entity_type == 'person' and entity.label in [1, 2]])
  2099. # # 招标/代理在同一句中交叉情况的处理
  2100. # for index in range(len(ent_list)):
  2101. # entity = ent_list[index]
  2102. # if entity.entity_text in roleSet and entity.label in [0, 1] and index+3<len(ent_list):
  2103. # if entity.sentence_index==ent_list[index+1].sentence_index==ent_list[index+2].sentence_index==ent_list[index+3].sentence_index:
  2104. # if ent_list[index+1].begin_index - entity.end_index < 30:
  2105. # if ent_list[index+1].entity_text in roleSet and ent_list[index+1].label in [0, 1] and entity.label!=ent_list[index+1].label:
  2106. # if ent_list[index+2].entity_type=="person" and ent_list[index+3].entity_type=="person" and \
  2107. # ent_list[index+2].label==3 and ent_list[index+3].label==3:
  2108. # ent_list[index + 1], ent_list[index + 2] = ent_list[index + 2], ent_list[index + 1]
  2109. #
  2110. #
  2111. # for index in range(len(ent_list)):
  2112. # entity = ent_list[index]
  2113. # if entity.entity_type=="person":
  2114. # if str(entity.label) == "0": # 2020/11/25 非联系人直接跳过
  2115. # continue
  2116. # if entity.values[entity.label]>on_value_person:
  2117. # if str(entity.label)=="1":
  2118. # for i in range(len(PackDict["Project"]["roleList"])):
  2119. # if PackDict["Project"]["roleList"][i].role_name=="tenderee":
  2120. # PackDict["Project"]["roleList"][i].linklist.append((entity.entity_text,entity.person_phone))
  2121. # link_person.append(entity.entity_text)
  2122. # link_ent.append(PackDict["Project"]["roleList"][i].entity_text)
  2123. # # add pointer_person
  2124. # for _entity in list_entity:
  2125. # if dict_role_id.get(str(_entity.label))=="tenderee":
  2126. # for i in range(len(PackDict["Project"]["roleList"])):
  2127. # if PackDict["Project"]["roleList"][i].entity_text==_entity.entity_text and PackDict["Project"]["roleList"][i].role_name=="tenderee":
  2128. # _entity.pointer_person = entity
  2129. # elif str(entity.label)=="2":
  2130. # for i in range(len(PackDict["Project"]["roleList"])):
  2131. # if PackDict["Project"]["roleList"][i].role_name=="agency":
  2132. # PackDict["Project"]["roleList"][i].linklist.append((entity.entity_text,entity.person_phone))
  2133. # link_person.append(entity.entity_text)
  2134. # link_ent.append(PackDict["Project"]["roleList"][i].entity_text)
  2135. # # add pointer_person
  2136. # for _entity in list_entity:
  2137. # if dict_role_id.get(str(_entity.label))=="agency":
  2138. # for i in range(len(PackDict["Project"]["roleList"])):
  2139. # if PackDict["Project"]["roleList"][i].entity_text==_entity.entity_text and PackDict["Project"]["roleList"][i].role_name=="agency":
  2140. # _entity.pointer_person = entity
  2141. # elif str(entity.label)=="3":
  2142. # if entity.entity_text in sure_person_set: # 2020/11/25 排除已经确定角色的联系人
  2143. # continue
  2144. # #not_link_person.append((entity_after.entity_text,entity_after.person_phone))
  2145. # other_person.append(entity.entity_text)
  2146. # temp_ent_list.append((entity.entity_text,entity.person_phone,entity))
  2147. #
  2148. # #if entity.entity_text in roleSet:
  2149. # if entity.entity_text in roleSet:
  2150. # if entity.label in [0,1]:
  2151. # other_ent.append(entity.entity_text)
  2152. # temp_ent_list.append((entity.entity_text, entity.label,entity))
  2153. # for behind_index in range(index+1, len(ent_list)):
  2154. # entity_after = ent_list[behind_index]
  2155. # if entity_after.sentence_index-entity.sentence_index>=1 or entity_after.entity_type in ['org','company']: # 只在本句中找联系人
  2156. # break
  2157. # if entity_after.values is not None:
  2158. # if entity_after.entity_type=="person":
  2159. # if str(entity_after.label) == "0": # 2020/11/25角色后面为非联系人 停止继续往后找
  2160. # break
  2161. # if entity_after.values[entity_after.label]>on_value_person:
  2162. # if str(entity_after.label)=="1":
  2163. # for i in range(len(PackDict["Project"]["roleList"])):
  2164. # if PackDict["Project"]["roleList"][i].role_name=="tenderee":
  2165. # PackDict["Project"]["roleList"][i].linklist.append((entity_after.entity_text,entity_after.person_phone))
  2166. # link_person.append(entity_after.entity_text)
  2167. # link_ent.append(PackDict["Project"]["roleList"][i].entity_text)
  2168. # elif str(entity_after.label)=="2":
  2169. # for i in range(len(PackDict["Project"]["roleList"])):
  2170. # if PackDict["Project"]["roleList"][i].role_name=="agency":
  2171. # PackDict["Project"]["roleList"][i].linklist.append((entity_after.entity_text,entity_after.person_phone))
  2172. # link_person.append(entity_after.entity_text)
  2173. # link_ent.append(PackDict["Project"]["roleList"][i].entity_text)
  2174. # elif str(entity_after.label)=="3":
  2175. # if entity_after.entity_text in sure_person_set: # 2020/11/25 如果姓名已经出现在确定角色联系人中则停止往后找
  2176. # break
  2177. # elif entity_after.begin_index - entity.end_index > 30:#2020/10/25 如果角色实体与联系人实体间隔大于阈值停止
  2178. # break
  2179. # for pack in PackDict.keys():
  2180. # for i in range(len(PackDict[pack]["roleList"])):
  2181. # if PackDict[pack]["roleList"][i].entity_text==entity.entity_text:
  2182. # #if entity_after.sentence_index-entity.sentence_index>1 and len(roleList[i].linklist)>0:
  2183. # #break
  2184. # PackDict[pack]["roleList"][i].linklist.append((entity_after.entity_text,entity_after.person_phone))
  2185. # link_person.append(entity_after.entity_text)
  2186. # #add pointer_person
  2187. # entity.pointer_person = entity_after
  2188. #
  2189. # not_link_person = [person for person in other_person if person not in link_person]
  2190. # not_link_ent = [ent for ent in other_ent if ent not in link_ent]
  2191. # if len(not_link_person) > 0 and len(not_link_ent) > 0 :
  2192. # item = temp_ent_list
  2193. # for i in range(len(item)):
  2194. # if item[i][0] in not_link_ent and item[i][1] == 0 and i+3 < len(item):
  2195. # if item[i+1][0] in other_ent and item[i+1][1] == 1 and item[i+2][0] in other_person and item[i+3][0] in other_person:
  2196. # item[i+1], item[i+2] = item[i+2], item[i+1]
  2197. # for i in range(len(item)-1, -1, -1):
  2198. # if item[i][0] in not_link_ent:
  2199. # for pack in PackDict.keys():
  2200. # for role in PackDict[pack]["roleList"]:
  2201. # if role.entity_text == item[i][0] and len(role.linklist) < 1:
  2202. # for j in range(i+1, len(item)):
  2203. # if item[j][0] in not_link_person:
  2204. # role.linklist.append(item[j][:2])
  2205. # #add pointer_person
  2206. # item[i][2].pointer_person = item[j][2]
  2207. # break
  2208. # else:
  2209. # break
  2210. # # 电话没有联系人的处理
  2211. # role_with_no_phone = []
  2212. # for i in range(len(PackDict["Project"]["roleList"])):
  2213. # if PackDict["Project"]["roleList"][i].role_name in ["tenderee","agency"]:
  2214. # if len(PackDict["Project"]["roleList"][i].linklist)==0: # 找出没有联系人的招标/代理人
  2215. # role_with_no_phone.append(PackDict["Project"]["roleList"][i].entity_text)
  2216. # else:
  2217. # phone_nums = 0
  2218. # for link in PackDict["Project"]["roleList"][i].linklist:
  2219. # if link[1]:
  2220. # phone_nums += 1
  2221. # break
  2222. # if not phone_nums:
  2223. # role_with_no_phone.append(PackDict["Project"]["roleList"][i].entity_text)
  2224. # if role_with_no_phone:
  2225. # phone_with_person = [entity.person_phone for entity in list_entity if entity.entity_type == "person"]
  2226. # # phone_with_person = [phone for phone in phone_with_person if phone]
  2227. #
  2228. # dict_index_sentence = {}
  2229. # for _sentence in list_sentence:
  2230. # dict_index_sentence[_sentence.sentence_index] = _sentence
  2231. # new_entity_list = [entity for entity in list_entity if entity.entity_type in ['org','company','person']]
  2232. # for index in range(len(new_entity_list)):
  2233. # entity = new_entity_list[index]
  2234. # if entity.entity_text in role_with_no_phone:
  2235. # e_sentence = dict_index_sentence[entity.sentence_index]
  2236. # entity_right = e_sentence.tokens[entity.end_index:entity.end_index+40]
  2237. # entity_right = "".join(entity_right)
  2238. # if index+1<len(new_entity_list) and entity_right.find(new_entity_list[index+1].entity_text)>-1:
  2239. # entity_right = entity_right[:entity_right.find(new_entity_list[index+1].entity_text)]
  2240. # have_phone = re.findall(phone,entity_right)
  2241. # if have_phone:
  2242. # _phone = have_phone[0]
  2243. # phone_begin = entity_right.find(_phone)
  2244. # if _phone not in phone_with_person and re.search(key_phone,entity_right[:phone_begin]):
  2245. # # entity.person_phone = _phone
  2246. # for i in range(len(PackDict["Project"]["roleList"])):
  2247. # if PackDict["Project"]["roleList"][i].entity_text == entity.entity_text:
  2248. # PackDict["Project"]["roleList"][i].linklist.append(('', _phone))
  2249. #寻找多标段招标金额
  2250. p_entity = len(list_entity)-1
  2251. set_tenderer_money = set()
  2252. list_tenderer_money = [] #2021/7/16 新增列表,倒序保存所有中标金额
  2253. unit_list = [] #2021/8/17 新增,保存金额单位
  2254. #遍历所有实体
  2255. while(p_entity>=0):
  2256. entity = list_entity[p_entity]
  2257. if entity.entity_type=="money":
  2258. # 2021/12/03 添加成本警戒线、保证金
  2259. if entity.notes in ['保证金', '成本警戒线']:
  2260. packagePointer, _flag = getPackage(PackageList, entity.sentence_index, entity.begin_index,
  2261. "money-" + str(entity.label), MAX_DIS=2, DIRECT="L")
  2262. if packagePointer is None:
  2263. packageName = "Project"
  2264. else:
  2265. packageName = packagePointer.entity_text
  2266. if packageName == "Project":
  2267. # if PackDict["Project"]["tendereeMoney"]<float(entity.entity_text):
  2268. # PackDict["Project"]["tendereeMoney"] = float(entity.entity_text)
  2269. if entity.notes=="保证金" and "bond" not in PackDict["Project"]:
  2270. PackDict["Project"]["bond"] = float(entity.entity_text)
  2271. elif entity.notes=="成本警戒线" and "cost_warning" not in PackDict["Project"]:
  2272. PackDict["Project"]["cost_warning"] = float(entity.entity_text)
  2273. else:
  2274. if entity.notes == "保证金" and "bond" not in PackDict[packageName]:
  2275. PackDict[packageName]["bond"] = float(entity.entity_text)
  2276. elif entity.notes == "成本警戒线" and "cost_warning" not in PackDict[packageName]:
  2277. PackDict[packageName]["cost_warning"] = float(entity.entity_text)
  2278. elif entity.values[entity.label]>=on_value:
  2279. if str(entity.label)=="1":
  2280. set_tenderer_money.add(float(entity.entity_text))
  2281. list_tenderer_money.append(float(entity.entity_text)) # 2021/7/16 新增列表,倒序保存所有中标金额
  2282. unit_list.append(entity.money_unit)
  2283. # if str(entity.label)=="0":
  2284. if str(entity.label)=="0" and entity.notes!='总投资':
  2285. '''
  2286. if p_entity>0:
  2287. p_before = list_entity[p_entity-1]
  2288. if p_before.entity_type=="money" and p_before.label==entity.label and p_before.entity_text==entity.entity_text and abs(entity.begin_index-p_before.end_index)<=2:
  2289. p_entity -= 1
  2290. continue
  2291. '''
  2292. packagePointer,_flag = getPackage(PackageList,entity.sentence_index,entity.begin_index,"money-"+str(entity.label),MAX_DIS=2,DIRECT="L")
  2293. if packagePointer is None:
  2294. packageName = "Project"
  2295. else:
  2296. packageName = packagePointer.entity_text
  2297. if packageName=="Project":
  2298. # if PackDict["Project"]["tendereeMoney"]<float(entity.entity_text):
  2299. # PackDict["Project"]["tendereeMoney"] = float(entity.entity_text)
  2300. if entity.values[entity.label]>on_value:
  2301. PackDict["Project"]["tendereeMoney"] = float(entity.entity_text)
  2302. PackDict["Project"]["tendereeMoneyUnit"] = entity.money_unit
  2303. else:
  2304. PackDict[packageName]["tendereeMoney"] = float(entity.entity_text)
  2305. PackDict[packageName]["tendereeMoneyUnit"] = entity.money_unit
  2306. #add pointer_tendereeMoney
  2307. packagePointer.pointer_tendereeMoney = entity
  2308. p_entity -= 1
  2309. #删除一个机构有多个角色的数据
  2310. #删除重复人、概率不回传
  2311. final_roleList = []
  2312. list_pop = []
  2313. set_tenderer_role = set()
  2314. dict_pack_tenderer_money = dict()
  2315. for pack in PackDict.keys():
  2316. #删除无效包
  2317. if PackDict[pack]["code"]=="" and PackDict[pack]["tendereeMoney"]==0 and len(PackDict[pack]["roleList"])==0:
  2318. list_pop.append(pack)
  2319. for i in range(len(PackDict[pack]["roleList"])):
  2320. if PackDict[pack]["roleList"][i].role_name=="win_tenderer":
  2321. if PackDict[pack]["roleList"][i].money==0:
  2322. set_tenderer_role.add(PackDict[pack]["roleList"][i])
  2323. dict_pack_tenderer_money[pack] = [PackDict[pack]["roleList"][i],set()]
  2324. #找到包的中投标金额
  2325. for _index in range(len(PackageList)):
  2326. if "hit" in PackageList[_index]:
  2327. for _hit in list(PackageList[_index]["hit"]):
  2328. _money = float(_hit.split("-")[1]) if _hit.split("-")[0]=="money" else None
  2329. if PackageList[_index]["name"] in dict_pack_tenderer_money and _money is not None:
  2330. dict_pack_tenderer_money[PackageList[_index]["name"]][1].add(_money)
  2331. #只找到一个中标人和中标金额
  2332. if len(set_tenderer_money)==1 and len(set_tenderer_role)==1:
  2333. list(set_tenderer_role)[0].money = list(set_tenderer_money)[0]
  2334. list(set_tenderer_role)[0].money_unit = unit_list[0]
  2335. # print('一个中标人一个金额:', list(set_tenderer_money)[0])
  2336. #找到一个中标人和多个招标金额
  2337. if len(set_tenderer_money)>1 and len(set_tenderer_role)==1:
  2338. _maxMoney = 0
  2339. _sumMoney = 0
  2340. for _m in list(set_tenderer_money):
  2341. _sumMoney += _m
  2342. if _m>_maxMoney:
  2343. _maxMoney = _m
  2344. if _sumMoney/_maxMoney==2:
  2345. list(set_tenderer_role)[0].money = _maxMoney
  2346. # print('一人多金额分项合计 取最大金额:', _maxMoney)
  2347. else:
  2348. # list(set_tenderer_role)[0].money = _maxMoney
  2349. if min(list_tenderer_money)>200000 and list_tenderer_money[-1]/min(list_tenderer_money)>9000:
  2350. list(set_tenderer_role)[0].money = min(list_tenderer_money)
  2351. list(set_tenderer_role)[0].money_unit = unit_list[list_tenderer_money.index(min(list_tenderer_money))]
  2352. # print('一人多金额 且最小的大于20万第一个金额比最小金额大几千倍的最小中标金额:', min(list_tenderer_money))
  2353. else:
  2354. list(set_tenderer_role)[0].money = list_tenderer_money[-1] # 2021/7/16 修改 不是单价合计方式取第一个中标金额
  2355. list(set_tenderer_role)[0].money_unit = unit_list[-1] # 金额单位
  2356. # print('一人多金额 取第一个中标金额:', list_tenderer_money[-1])
  2357. #每个包都只找到一个金额
  2358. _flag_pack_money = True
  2359. for k,v in dict_pack_tenderer_money.items():
  2360. if len(v[1])!=1:
  2361. _flag_pack_money = False
  2362. if _flag_pack_money and len(PackageSet)==len(dict_pack_tenderer_money.keys()):
  2363. for k,v in dict_pack_tenderer_money.items():
  2364. v[0].money = list(v[1])[0]
  2365. # print('k,v in dict_pack_tenderer_money.items', k, v)
  2366. # 2021/7/16 #增加判断中标金额是否远大于招标金额逻辑
  2367. for pack in PackDict.keys():
  2368. for i in range(len(PackDict[pack]["roleList"])):
  2369. if PackDict[pack]["tendereeMoney"] > 0:
  2370. # print('金额数据类型:',type(PackDict[pack]["roleList"][i].money))
  2371. if float(PackDict[pack]["roleList"][i].money) >10000000 and \
  2372. float(PackDict[pack]["roleList"][i].money)/float(PackDict[pack]["tendereeMoney"])>=1000:
  2373. PackDict[pack]["roleList"][i].money = float(PackDict[pack]["roleList"][i].money) / 10000
  2374. # print('招标金额校正中标金额')
  2375. # 2022/04/01 #增加判断中标金额是否远小于招标金额逻辑,比例相差10000倍左右(中标金额“万”单位丢失或未识别)
  2376. for pack in PackDict.keys():
  2377. for i in range(len(PackDict[pack]["roleList"])):
  2378. if PackDict[pack]["tendereeMoney"] > 0 and float(PackDict[pack]["roleList"][i].money) > 0.:
  2379. if float(PackDict[pack]["roleList"][i].money) < 1000 and \
  2380. float(PackDict[pack]["tendereeMoney"])/float(PackDict[pack]["roleList"][i].money)>=9995 and \
  2381. float(PackDict[pack]["tendereeMoney"])/float(PackDict[pack]["roleList"][i].money)<11000:
  2382. PackDict[pack]["roleList"][i].money = float(PackDict[pack]["roleList"][i].money) * 10000
  2383. # 2021/7/19 #增加判断中标金额是否远大于第二三中标金额
  2384. for pack in PackDict.keys():
  2385. tmp_moneys = []
  2386. for i in range(len(PackDict[pack]["roleList"])):
  2387. if float(PackDict[pack]["roleList"][i].money) >100000:
  2388. tmp_moneys.append(float(PackDict[pack]["roleList"][i].money))
  2389. if len(tmp_moneys)>2 and max(tmp_moneys)/min(tmp_moneys)>1000:
  2390. for i in range(len(PackDict[pack]["roleList"])):
  2391. if float(PackDict[pack]["roleList"][i].money)/min(tmp_moneys)>1000:
  2392. PackDict[pack]["roleList"][i].money = float(PackDict[pack]["roleList"][i].money) / 10000
  2393. # print('通过其他中标人投标金额校正中标金额')
  2394. for item in list_pop:
  2395. PackDict.pop(item)
  2396. # 公告中只有"招标人"且无"联系人"链接时
  2397. if len(PackDict)==1:
  2398. k = list(PackDict.keys())[0]
  2399. if len(PackDict[k]["roleList"])==1:
  2400. if PackDict[k]["roleList"][0].role_name == "tenderee":
  2401. if not PackDict[k]["roleList"][0].linklist:
  2402. get_contacts = False
  2403. if not get_contacts:
  2404. # 根据大纲Outline类召回联系人
  2405. for outline in list_outline:
  2406. if re.search("联系人|联系方|联系方式|联系电话|电话|负责人|与.{2,4}联系",outline.outline_summary):
  2407. for t_person in [p for p in temporary_list2 if p.entity_type=='person' and p.label==3]:
  2408. if words_num_dict[t_person.sentence_index] + t_person.wordOffset_begin >= words_num_dict[outline.sentence_begin_index] + outline.wordOffset_begin and words_num_dict[
  2409. t_person.sentence_index] + t_person.wordOffset_end < words_num_dict[outline.sentence_end_index] + outline.wordOffset_end:
  2410. if t_person.person_phone:
  2411. _phone = [p.entity_text for p in t_person.person_phone]
  2412. for _p in _phone:
  2413. PackDict[k]["roleList"][0].linklist.append((t_person.entity_text, _p))
  2414. get_contacts = True
  2415. break
  2416. elif words_num_dict[t_person.sentence_index] + t_person.wordOffset_begin >= \
  2417. words_num_dict[outline.sentence_end_index] + outline.wordOffset_end:
  2418. break
  2419. if not get_contacts:
  2420. sentence_phone = phone.findall(outline.outline_text)
  2421. if sentence_phone:
  2422. PackDict[k]["roleList"][0].linklist.append(("", sentence_phone[0]))
  2423. get_contacts = True
  2424. break
  2425. if not get_contacts:
  2426. # 直接取文中倒数第一个联系人
  2427. for _entity in temporary_list2[::-1]:
  2428. if _entity.entity_type=='person' and _entity.label==3:
  2429. if _entity.person_phone:
  2430. _phone = [p.entity_text for p in _entity.person_phone]
  2431. for _p in _phone:
  2432. PackDict[k]["roleList"][0].linklist.append((_entity.entity_text, _p))
  2433. get_contacts = True
  2434. break
  2435. if not get_contacts:
  2436. # 如果文中只有一个“phone”实体,则直接取为联系人电话
  2437. if len(phone_entitys) == 1:
  2438. PackDict[k]["roleList"][0].linklist.append(("", phone_entitys[0].entity_text))
  2439. get_contacts = True
  2440. if not get_contacts:
  2441. # 通过大纲Outline类直接取电话
  2442. if len(new_split_list) > 1:
  2443. for _start, _end in new_split_list:
  2444. temp_sentence = _content[_start:_end]
  2445. sentence_outline = temp_sentence.split(",::")[0]
  2446. if re.search("联系人|联系方|联系方式|联系电话|电话|负责人|与.{2,4}联系", sentence_outline):
  2447. sentence_phone = phone.findall(temp_sentence)
  2448. if sentence_phone:
  2449. PackDict[k]["roleList"][0].linklist.append(("", sentence_phone[0]))
  2450. get_contacts = True
  2451. break
  2452. if not get_contacts:
  2453. # 通过正则提取句子段落进行提取电话
  2454. contacts_person = "(?:联系人|联系方|联系方式|负责人|电话|联系电话)[::]?"
  2455. tenderee_pattern = "(?:(?:采购|招标|议价|议标|比选)(?:人|公司|单位|组织|部门)|建设(?:单位|业主)|(?:采购|招标|甲)方|询价单位|项目业主|业主|业主单位)[^。]{0,5}"
  2456. contact_pattern_list = [tenderee_pattern + contacts_person,
  2457. "(?:采购[^。,]{0,2}项目|采购事项|招标)[^。,]{0,4}" + contacts_person,
  2458. "(?:项目|采购)[^。,]{0,4}" + contacts_person,
  2459. "(?:报名|报价|业务咨询|业务|投标咨询)[^。,]{0,4}" + contacts_person, ]
  2460. for _pattern in contact_pattern_list:
  2461. get_tenderee_contacts = False
  2462. for regular_match in re.finditer(_pattern, _content):
  2463. match_text = _content[regular_match.end():regular_match.end() + 40]
  2464. match_text = match_text.split("。")[0]
  2465. sentence_phone = phone.findall(match_text)
  2466. if sentence_phone:
  2467. PackDict[k]["roleList"][0].linklist.append(("", sentence_phone[0]))
  2468. get_tenderee_contacts = True
  2469. break
  2470. if get_tenderee_contacts:
  2471. break
  2472. for pack in PackDict.keys():
  2473. for i in range(len(PackDict[pack]["roleList"])):
  2474. PackDict[pack]["roleList"][i] = PackDict[pack]["roleList"][i].getString()
  2475. return PackDict
  2476. def initPackageAttr(RoleList,PackageSet):
  2477. '''
  2478. @summary: 根据拿到的roleList和packageSet初始化接口返回的数据
  2479. '''
  2480. packDict = dict()
  2481. packDict["Project"] = {"code":"","tendereeMoney":0,"roleList":[], 'tendereeMoneyUnit':''}
  2482. for item in list(PackageSet):
  2483. packDict[item] = {"code":"","tendereeMoney":0,"roleList":[], 'tendereeMoneyUnit':''}
  2484. for item in RoleList:
  2485. if packDict[item.packageName]["code"] =="":
  2486. packDict[item.packageName]["code"] = item.packageCode
  2487. # packDict[item.packageName]["roleList"].append(Role(item.role_name,item.entity_text,0,0,0.0,[]))
  2488. packDict[item.packageName]["roleList"].append(Role(item.role_name,item.entity_text,0,0,0.0,[])) #Role(角色名称,实体名称,角色阈值,金额,金额阈值,连接列表,金额单位)
  2489. return packDict
  2490. def getPackageRoleMoney(list_sentence,list_entity,list_outline):
  2491. '''
  2492. @param:
  2493. list_sentence:文章的句子list
  2494. list_entity:文章的实体list
  2495. @return: 拿到文章的包-标段号-角色-实体名称-金额-联系人-联系电话
  2496. '''
  2497. # print("=1")
  2498. theRole = getRoleList(list_sentence,list_entity)
  2499. if not theRole:
  2500. return []
  2501. RoleList,RoleSet,PackageList,PackageSet = theRole
  2502. '''
  2503. for item in PackageList:
  2504. # print(item)
  2505. '''
  2506. PackDict = initPackageAttr(RoleList, PackageSet)
  2507. PackDict = findAttributeAfterEntity(PackDict, RoleSet, PackageList, PackageSet, list_sentence, list_entity, list_outline)
  2508. return PackDict
  2509. def turnBidWay(bidway):
  2510. if bidway in ("邀请招标","采购方式:邀请"):
  2511. return "邀请招标"
  2512. elif bidway in ("询价","询单","询比","采购方式:询价"):
  2513. return "询价"
  2514. elif bidway in ("竞谈","竞争性谈判","公开竞谈"):
  2515. return "竞争性谈判"
  2516. elif bidway in ("竞争性磋商","磋商"):
  2517. return "竞争性磋商"
  2518. elif bidway in ("竞价","竞标","电子竞价","以电子竞价","电子书面竞投"):
  2519. return "竞价"
  2520. elif bidway in ("公开招标","网上电子投标","网上招标","采购方式:公开","招标为其他"):
  2521. return "公开招标"
  2522. elif bidway in ("单一来源"):
  2523. return "单一来源"
  2524. elif bidway in ("比选"):
  2525. return "比选"
  2526. else:
  2527. return "其他"
  2528. my_time_format_pattern = re.compile("((?P<year>\d{4}|\d{2})\s*[-\/年\.]\s*(?P<month>\d{1,2})\s*[-\/月\.]\s*(?P<day>\d{1,2}))")
  2529. import time
  2530. def my_timeFormat(_time):
  2531. current_year = time.strftime("%Y",time.localtime())
  2532. all_match = re.finditer(my_time_format_pattern,_time)
  2533. time_list = []
  2534. for _match in all_match:
  2535. if len(_match.group())>0:
  2536. legal = True
  2537. year = ""
  2538. month = ""
  2539. day = ""
  2540. for k,v in _match.groupdict().items():
  2541. if k=="year":
  2542. year = v
  2543. if k=="month":
  2544. month = v
  2545. if k=="day":
  2546. day = v
  2547. if year!="":
  2548. if len(year)==2:
  2549. year = "20"+year
  2550. if int(year)>int(current_year):
  2551. legal = False
  2552. else:
  2553. legal = False
  2554. if month!="":
  2555. if int(month)>12:
  2556. legal = False
  2557. else:
  2558. legal = False
  2559. if day!="":
  2560. if int(day)>31:
  2561. legal = False
  2562. else:
  2563. legal = False
  2564. if legal:
  2565. # return "%s-%s-%s"%(year,month.rjust(2,"0"),day.rjust(2,"0"))
  2566. time_list.append("%s-%s-%s"%(year,month.rjust(2,"0"),day.rjust(2,"0")))
  2567. return time_list
  2568. def getTimeAttributes(list_entity,list_sentence):
  2569. time_entitys = [i for i in list_entity if i.entity_type=='time']
  2570. time_entitys = sorted(time_entitys,key=lambda x:(x.sentence_index, x.begin_index))
  2571. list_sentence = sorted(list_sentence,key=lambda x:x.sentence_index)
  2572. dict_time = {
  2573. "time_release": [], # 1 发布时间
  2574. "time_bidopen": [], # 2 开标时间
  2575. "time_bidclose": [], # 3 截标时间
  2576. 'time_bidstart': [], # 12 投标(开始)时间、响应文件接收(开始)时间
  2577. 'time_publicityStart': [], # 4 公示开始时间(公示时间、公示期)
  2578. 'time_publicityEnd': [], # 5 公示截止时间
  2579. 'time_getFileStart': [], # 6 文件获取开始时间(文件获取时间)
  2580. 'time_getFileEnd': [], # 7 文件获取截止时间
  2581. 'time_registrationStart': [], # 8 报名开始时间(报名时间)
  2582. 'time_registrationEnd': [], # 9 报名截止时间
  2583. 'time_earnestMoneyStart': [], #10 保证金递交开始时间(保证金递交时间)
  2584. 'time_earnestMoneyEnd': [] , # 11 保证金递交截止时间
  2585. 'time_commencement':[] , #13 开工日期
  2586. 'time_completion': [] # 14 竣工日期
  2587. }
  2588. last_sentence_index = 0
  2589. last_time_type = ""
  2590. last_time_index = {
  2591. 'time_bidstart':"time_bidclose",
  2592. 'time_publicityStart':"time_publicityEnd",
  2593. 'time_getFileStart':"time_getFileEnd",
  2594. 'time_registrationStart':"time_registrationEnd",
  2595. 'time_earnestMoneyStart':"time_earnestMoneyEnd",
  2596. 'time_commencement':"time_completion",
  2597. }
  2598. for entity in time_entitys:
  2599. sentence_text = list_sentence[entity.sentence_index].sentence_text
  2600. entity_left = sentence_text[max(0, entity.wordOffset_begin - 2):entity.wordOffset_begin]
  2601. entity_right = sentence_text[entity.wordOffset_end:entity.wordOffset_end + 3]
  2602. label_prob = entity.values[entity.label]
  2603. entity_text = entity.entity_text
  2604. extract_time = my_timeFormat(entity_text)
  2605. if extract_time:
  2606. if re.search("至|到", entity_left):
  2607. if entity.sentence_index == last_sentence_index:
  2608. time_type = last_time_index.get(last_time_type)
  2609. if time_type:
  2610. dict_time[time_type].append((extract_time[0], 0.5 + label_prob / 10))
  2611. last_time_type = ""
  2612. continue
  2613. if entity.label!=0:
  2614. if entity.label==1 and label_prob>0.5:
  2615. dict_time['time_release'].append((extract_time[0],label_prob))
  2616. last_time_type = 'time_release'
  2617. elif entity.label==2 and label_prob>0.5:
  2618. dict_time['time_bidopen'].append((extract_time[0],label_prob))
  2619. last_time_type = 'time_bidopen'
  2620. elif entity.label==3 and label_prob>0.5:
  2621. dict_time['time_bidclose'].append((extract_time[0],label_prob))
  2622. last_time_type = 'time_bidclose'
  2623. elif entity.label==12 and label_prob>0.5:
  2624. if len(extract_time)==1:
  2625. if re.search("前|止|截止",entity_right) or re.search("至|止|到",entity_left) or re.search("前",entity_text[-2:]):
  2626. dict_time['time_bidclose'].append((extract_time[0], label_prob))
  2627. last_time_type = 'time_bidclose'
  2628. else:
  2629. dict_time['time_bidstart'].append((extract_time[0], label_prob))
  2630. last_time_type = 'time_bidstart'
  2631. else:
  2632. dict_time['time_bidstart'].append((extract_time[0],label_prob))
  2633. dict_time['time_bidclose'].append((extract_time[1],label_prob))
  2634. last_time_type = ''
  2635. elif entity.label==4 and label_prob>0.5:
  2636. if len(extract_time)==1:
  2637. if re.search("前|止|截止",entity_right) or re.search("至|止|到",entity_left) or re.search("前",entity_text[-2:]):
  2638. dict_time['time_publicityEnd'].append((extract_time[0], label_prob))
  2639. last_time_type = 'time_publicityEnd'
  2640. else:
  2641. dict_time['time_publicityStart'].append((extract_time[0], label_prob))
  2642. last_time_type = 'time_publicityStart'
  2643. else:
  2644. dict_time['time_publicityStart'].append((extract_time[0],label_prob))
  2645. dict_time['time_publicityEnd'].append((extract_time[1],label_prob))
  2646. last_time_type = ''
  2647. elif entity.label==5 and label_prob>0.5:
  2648. if len(extract_time)==1:
  2649. dict_time['time_publicityEnd'].append((extract_time[0], label_prob))
  2650. last_time_type = 'time_publicityEnd'
  2651. else:
  2652. dict_time['time_publicityStart'].append((extract_time[0],label_prob))
  2653. dict_time['time_publicityEnd'].append((extract_time[1],label_prob))
  2654. last_time_type = ''
  2655. elif entity.label==6 and label_prob>0.5:
  2656. if len(extract_time)==1:
  2657. if re.search("前|止|截止",entity_right) or re.search("至|止|到",entity_left) or re.search("前",entity_text[-2:]):
  2658. dict_time['time_getFileEnd'].append((extract_time[0], label_prob))
  2659. last_time_type = 'time_getFileEnd'
  2660. else:
  2661. dict_time['time_getFileStart'].append((extract_time[0], label_prob))
  2662. last_time_type = 'time_getFileStart'
  2663. else:
  2664. dict_time['time_getFileStart'].append((extract_time[0],label_prob))
  2665. dict_time['time_getFileEnd'].append((extract_time[1],label_prob))
  2666. last_time_type = ''
  2667. elif entity.label==7 and label_prob>0.5:
  2668. if len(extract_time)==1:
  2669. dict_time['time_getFileEnd'].append((extract_time[0], label_prob))
  2670. last_time_type = 'time_getFileEnd'
  2671. else:
  2672. dict_time['time_getFileStart'].append((extract_time[0],label_prob))
  2673. dict_time['time_getFileEnd'].append((extract_time[1],label_prob))
  2674. last_time_type = ''
  2675. elif entity.label==8 and label_prob>0.5:
  2676. if len(extract_time)==1:
  2677. if re.search("前|止|截止",entity_right) or re.search("至|止|到",entity_left) or re.search("前",entity_text[-2:]):
  2678. dict_time['time_registrationEnd'].append((extract_time[0], label_prob))
  2679. last_time_type = 'time_registrationEnd'
  2680. else:
  2681. dict_time['time_registrationStart'].append((extract_time[0], label_prob))
  2682. last_time_type = 'time_registrationStart'
  2683. else:
  2684. dict_time['time_registrationStart'].append((extract_time[0],label_prob))
  2685. dict_time['time_registrationEnd'].append((extract_time[1],label_prob))
  2686. last_time_type = ''
  2687. elif entity.label==9 and label_prob>0.5:
  2688. if len(extract_time)==1:
  2689. dict_time['time_registrationEnd'].append((extract_time[0], label_prob))
  2690. last_time_type = 'time_registrationEnd'
  2691. else:
  2692. dict_time['time_registrationStart'].append((extract_time[0],label_prob))
  2693. dict_time['time_registrationEnd'].append((extract_time[1],label_prob))
  2694. last_time_type = ''
  2695. elif entity.label==10 and label_prob>0.5:
  2696. if len(extract_time)==1:
  2697. if re.search("前|止|截止",entity_right) or re.search("至|止|到",entity_left) or re.search("前",entity_text[-2:]):
  2698. dict_time['time_earnestMoneyEnd'].append((extract_time[0], label_prob))
  2699. last_time_type = 'time_earnestMoneyEnd'
  2700. else:
  2701. dict_time['time_earnestMoneyStart'].append((extract_time[0], label_prob))
  2702. last_time_type = 'time_earnestMoneyStart'
  2703. else:
  2704. dict_time['time_earnestMoneyStart'].append((extract_time[0],label_prob))
  2705. dict_time['time_earnestMoneyEnd'].append((extract_time[1],label_prob))
  2706. last_time_type = ''
  2707. elif entity.label==11 and label_prob>0.5:
  2708. if len(extract_time)==1:
  2709. dict_time['time_earnestMoneyEnd'].append((extract_time[0], label_prob))
  2710. last_time_type = 'time_earnestMoneyEnd'
  2711. else:
  2712. dict_time['time_earnestMoneyStart'].append((extract_time[0],label_prob))
  2713. dict_time['time_earnestMoneyEnd'].append((extract_time[1],label_prob))
  2714. last_time_type = ''
  2715. elif entity.label==13 and label_prob>0.5:
  2716. if len(extract_time)==1:
  2717. if re.search("前|止|截止",entity_right) or re.search("至|止|到",entity_left) or re.search("前",entity_text[-2:]):
  2718. dict_time['time_completion'].append((extract_time[0], label_prob))
  2719. last_time_type = 'time_completion'
  2720. else:
  2721. dict_time['time_commencement'].append((extract_time[0], label_prob))
  2722. last_time_type = 'time_commencement'
  2723. else:
  2724. dict_time['time_commencement'].append((extract_time[0],label_prob))
  2725. dict_time['time_completion'].append((extract_time[1],label_prob))
  2726. last_time_type = ''
  2727. elif entity.label==14 and label_prob>0.5:
  2728. if len(extract_time)==1:
  2729. dict_time['time_completion'].append((extract_time[0], label_prob))
  2730. last_time_type = 'time_completion'
  2731. else:
  2732. dict_time['time_commencement'].append((extract_time[0],label_prob))
  2733. dict_time['time_completion'].append((extract_time[1],label_prob))
  2734. last_time_type = ''
  2735. else:
  2736. last_time_type = ""
  2737. else:
  2738. last_time_type = ""
  2739. else:
  2740. last_time_type = ""
  2741. last_sentence_index = entity.sentence_index
  2742. result_dict = dict((key,"") for key in dict_time.keys())
  2743. for time_type,value in dict_time.items():
  2744. list_time = dict_time[time_type]
  2745. if list_time:
  2746. list_time.sort(key=lambda x:x[1],reverse=True)
  2747. result_dict[time_type] = list_time[0][0]
  2748. return result_dict
  2749. def getOtherAttributes(list_entity):
  2750. dict_other = {"moneysource":"",
  2751. "person_review":[],
  2752. "serviceTime":"",
  2753. "product":[],
  2754. "total_tendereeMoney":0,
  2755. "total_tendereeMoneyUnit":''}
  2756. for entity in list_entity:
  2757. if entity.entity_type == 'bidway':
  2758. dict_other["bidway"] = turnBidWay(entity.entity_text)
  2759. elif entity.entity_type=='moneysource':
  2760. dict_other["moneysource"] = entity.entity_text
  2761. elif entity.entity_type=='serviceTime':
  2762. if re.search("日|天|年|月|周|星期", entity.entity_text) or re.search("\d{4}[\-\./]\d{1,2}", entity.entity_text):
  2763. if not entity.in_attachment:
  2764. dict_other["serviceTime"] = entity.entity_text
  2765. else:
  2766. if not dict_other["serviceTime"]:
  2767. dict_other["serviceTime"] = entity.entity_text
  2768. elif entity.entity_type=="person" and entity.label ==4:
  2769. dict_other["person_review"].append(entity.entity_text)
  2770. elif entity.entity_type=='product':
  2771. dict_other["product"].append(entity.entity_text)
  2772. elif entity.entity_type=='money' and entity.notes=='总投资' and dict_other["total_tendereeMoney"]<float(entity.entity_text):
  2773. dict_other["total_tendereeMoney"] = float(entity.entity_text)
  2774. dict_other["total_tendereeMoneyUnit"] = entity.money_unit
  2775. dict_other["product"] = list(set(dict_other["product"]))
  2776. return dict_other
  2777. def getMoneyRange(RoleList):
  2778. pass
  2779. def getPREMs(list_sentences,list_entitys,list_articles,list_outlines):
  2780. '''
  2781. @param:
  2782. list_sentence:所有文章的句子list
  2783. list_entity:所有文章的实体list
  2784. @return:list of dict which include文章的包-角色-实体名称-金额-联系人-联系电话
  2785. '''
  2786. result = []
  2787. for list_sentence,list_entity,list_article,list_outline in zip(list_sentences,list_entitys,list_articles,list_outlines):
  2788. RoleList = getPackageRoleMoney(list_sentence,list_entity,list_outline)
  2789. result.append(dict({"prem": RoleList, "docid": list_article.doc_id},
  2790. **getTimeAttributes(list_entity, list_sentence),
  2791. **{"fingerprint": list_article.fingerprint,
  2792. "match_enterprise": list_article.match_enterprise,
  2793. "match_enterprise_type": list_article.match_enterprise_type,
  2794. "process_time": getCurrent_date(),
  2795. "attachmentTypes": list_article.attachmentTypes, "bidway": list_article.bidway}))
  2796. # result.append(dict({"prem":RoleList,"docid":list_article.doc_id},**getOtherAttributes(list_entity),**getTimeAttributes(list_entity,list_sentence),
  2797. # **{"fingerprint":list_article.fingerprint,"match_enterprise":list_article.match_enterprise,
  2798. # "match_enterprise_type":list_article.match_enterprise_type,"process_time":getCurrent_date(),
  2799. # "attachmentTypes":list_article.attachmentTypes, "bidway": list_article.bidway}))
  2800. return result
  2801. if __name__=="__main__":
  2802. '''
  2803. conn = getConnection()
  2804. cursor = conn.cursor()
  2805. #sql = " select distinct A.doc_id from entity_mention A,test_predict_role B where A.entity_id=B.entity_id limit 200"
  2806. sql = " select B.doc_id,B.prem from articles_processed A, articles_validation B where A.id=B.doc_id "
  2807. result = []
  2808. cursor.execute(sql)
  2809. rows = cursor.fetchall()
  2810. count = 0
  2811. for row in rows:
  2812. count += 1
  2813. # print(count)
  2814. doc_id = row[0]
  2815. roleList = getPackageRoleMoney(doc_id)
  2816. result.append([doc_id,str(roleList),row[1]])
  2817. ''''''
  2818. with codecs.open("getAttribute.html","w",encoding="utf8") as f:
  2819. f.write('<html><head>\
  2820. <meta http-equiv="Content-Type"\
  2821. content="text/html; charset=UTF-8">\
  2822. </head>\
  2823. <body bgcolor="#FFFFFF">\
  2824. <table border="1">\
  2825. <tr>\
  2826. <td>doc_id</td>\
  2827. <td>角色</td>\
  2828. </tr>')
  2829. for item in result:
  2830. f.write("<tr>"+"<td>"+item[0]+"</td>"+"<td>"+item[1]+"</td>"+"<td>"+item[2]+"</td>"+"</tr>")
  2831. f.write("</table></body>")
  2832. '''