html_2_kvtree.py 121 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639
  1. #coding:utf8
  2. from bs4 import BeautifulSoup
  3. import json
  4. import re
  5. import traceback
  6. import logging
  7. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  8. logger = logging.getLogger(__name__)
  9. logger.setLevel(logging.INFO)
  10. from BiddingKG.dl.interface.Preprocessing import tableToText
  11. from uuid import uuid4
  12. def log(msg):
  13. '''
  14. @summary:打印信息
  15. '''
  16. logger.info(msg)
  17. class DotDict(dict):
  18. def __getattr__(self,name):
  19. try:
  20. return self[name]
  21. except KeyError:
  22. raise AttributeError("No attribute '%s'" % name)
  23. def __setattr__(self,name,value):
  24. self[name] = value
  25. def get_tables(soup,dict_table = None):
  26. is_first = False
  27. if dict_table is None:
  28. dict_table = {"children":[]}
  29. is_first = True
  30. if soup and soup.name:
  31. childs = soup.contents
  32. else:
  33. childs = []
  34. # tr+tbody
  35. _flag = False
  36. if len(childs)>=2:
  37. if childs[0].name=="tr" and childs[1].name=="tbody":
  38. childs[1].insert(0,copy.copy(childs[0]))
  39. childs[0].decompose()
  40. _flag = True
  41. childs_bak = childs
  42. # tbody+tbody
  43. _flag = False
  44. if soup and soup.name:
  45. childs = soup.find_all("tbody",recursive=False)
  46. if len(childs)>=2:
  47. if childs[0].name=="tbody" and childs[1].name=="tbody":
  48. child0_tr = childs[0].find_all("tr",recursive=False)
  49. has_td_count = 0
  50. tr_line = None
  51. for tr in child0_tr:
  52. if len(tr.find_all(["td", "th"],recursive=False))>0:
  53. has_td_count += 1
  54. tr_line = tr
  55. if has_td_count==1:
  56. childs[1].insert(0,copy.copy(tr_line))
  57. childs[0].decompose()
  58. _flag = True
  59. childs = childs_bak
  60. for child in childs:
  61. _d = {"children":[]}
  62. if child.name in ("table","tbody"):
  63. if len(child.find_all("tr",recursive=False))>0:
  64. # _d["table"] = str(child)
  65. _d["table"] = child
  66. dict_table["children"].append(_d)
  67. child_dict_table = get_tables(child,_d)
  68. if is_first:
  69. if soup.name in ("table","tbody"):
  70. if not _flag:
  71. if len(soup.find_all("tr",recursive=False))>0:
  72. # dict_table["table"] = str(soup)
  73. dict_table["table"] = soup
  74. dict_table = squeeze_tables(dict_table)
  75. return dict_table
  76. def squeeze_tables(dict_table):
  77. _i = -1
  78. new_children = []
  79. for child in dict_table["children"]:
  80. _i += 1
  81. child_table = squeeze_tables(child)
  82. if child_table is not None:
  83. new_children.append(child_table)
  84. if dict_table.get("table") is not None:
  85. if len(new_children)>0:
  86. dict_table["children"] = new_children
  87. else:
  88. del dict_table["children"]
  89. return dict_table
  90. if len(new_children)==1:
  91. return new_children[0]
  92. if len(new_children)>1:
  93. dict_table["children"] = new_children
  94. return dict_table
  95. return None
  96. def table_to_tree(soup,json_obj=None):
  97. if json_obj is None:
  98. json_obj = DotDict({"tag": "table","children":[]})
  99. dict_table = get_tables(soup)
  100. if dict_table == None: # 20241226 修复报错
  101. dict_table = {}
  102. children = dict_table.get("children",[])
  103. for child in children:
  104. _d = DotDict({"tag": "table","children":[]})
  105. json_obj["children"].append(_d)
  106. table = child.get("table")
  107. if table is not None:
  108. table_id = str(uuid4())
  109. table_to_tree(table,_d)
  110. table = dict_table.get("table")
  111. if table is not None:
  112. table_id = str(uuid4())
  113. json_obj["table_id"] = table_id
  114. soup, kv_list, text = tableToText(table,return_kv=True)
  115. _flag = False
  116. if soup and soup.name:
  117. if soup.contents:
  118. _flag = True
  119. soup.contents[0].insert_before(table_id)
  120. if not _flag:
  121. soup.insert_before(table_id)
  122. json_obj["text"] = text
  123. json_obj["kv"] = kv_list
  124. for _d in kv_list:
  125. _d["position"] = {"key_begin_sentence":0,
  126. "key_begin_sentence_start":_d.get("key_sen_index",0),
  127. "key_end_sentence":0,
  128. "key_end_sentence_end":_d.get("key_sen_index",0)+len(_d.get("key","")),
  129. "value_begin_sentence":0,
  130. "value_begin_sentence_start":_d.get("value_sen_index",0),
  131. "value_end_sentence":0,
  132. "value_end_sentence_end":_d.get("value_sen_index",0)+len(_d.get("value",""))
  133. }
  134. if "key_sen_index" in _d:
  135. _d.pop("key_sen_index")
  136. if "value_sen_index" in _d:
  137. _d.pop("value_sen_index")
  138. return json_obj
  139. def update_table_position(table,sentence_index):
  140. def get_table_idx_lengths(list_table_id,index):
  141. _length = 0
  142. for _d in list_table_id:
  143. table_id = _d.get("table_id")
  144. idx = _d.get("idx",-1)
  145. if idx>=0 and _idx<=index:
  146. _length += len(table_id)
  147. return _length
  148. def get_sentence_index(list_sent_span,idx):
  149. list_sent_span.sort(key=lambda x:x[0])
  150. for _i in range(len(list_sent_span)):
  151. if list_sent_span[_i][0]<=idx and idx<=list_sent_span[_i][1]:
  152. return _i
  153. return 0
  154. def get_list_tables(table,list_table=[]):
  155. table_id = table.get("table_id")
  156. if table_id:
  157. list_table.append(table)
  158. childs = table.get("children",[])
  159. for child in childs:
  160. get_list_tables(child,list_table)
  161. return list_table
  162. tables = get_list_tables(table)
  163. if tables:
  164. list_table_id = []
  165. text = tables[0].get("text","")
  166. for table in tables:
  167. table_id = table.get("table_id")
  168. if table_id:
  169. _idx = text.find(table_id)
  170. list_table_id.append({"table_id":table_id,"idx":_idx})
  171. if _idx>=0:
  172. kv_list = table.get("kv",[])
  173. for _d in kv_list:
  174. _d["position"]["key_begin_sentence_start"] += _idx
  175. _d["position"]["key_end_sentence_end"] += _idx
  176. _d["position"]["value_begin_sentence_start"] += _idx
  177. _d["position"]["value_end_sentence_end"] += _idx
  178. # remove table_id
  179. for table in tables:
  180. table_id = table.get("table_id")
  181. if table_id:
  182. kv_list = table.get("kv",[])
  183. for _d in kv_list:
  184. _length = get_table_idx_lengths(list_table_id,_d["position"]["key_begin_sentence_start"])
  185. _d["position"]["key_begin_sentence_start"] -= _length
  186. _length = get_table_idx_lengths(list_table_id,_d["position"]["key_end_sentence_end"])
  187. _d["position"]["key_end_sentence_end"] -= _length
  188. _length = get_table_idx_lengths(list_table_id,_d["position"]["value_begin_sentence_start"])
  189. _d["position"]["value_begin_sentence_start"] -= _length
  190. _length = get_table_idx_lengths(list_table_id,_d["position"]["value_end_sentence_end"])
  191. _d["position"]["value_end_sentence_end"] -= _length
  192. for table in tables:
  193. if table.get("table_id"):
  194. text = table.get("text","")
  195. for _d in list_table_id:
  196. table_id = _d.get("table_id")
  197. text = text.replace(table_id,"")
  198. table["text"] = text
  199. # split sentence
  200. text = tables[0].get("text","")
  201. list_sentence = str(text).split("。")
  202. list_sent_span = []
  203. _begin = 0
  204. for _i in range(len(list_sentence)):
  205. list_sentence[_i] += "。"
  206. _end = _begin+len(list_sentence[_i])
  207. list_sent_span.append([_begin,_end])
  208. _begin = _end
  209. tables[0]["sentences"] = list_sentence
  210. for table in tables:
  211. kv_list = table.get("kv",[])
  212. for _d in kv_list:
  213. key_begin_sentence = get_sentence_index(list_sent_span,_d["position"]["key_begin_sentence_start"])
  214. _d["position"]["key_begin_sentence"] = key_begin_sentence+sentence_index
  215. key_end_sentence = get_sentence_index(list_sent_span,_d["position"]["key_end_sentence_end"])
  216. _d["position"]["key_end_sentence"] = key_end_sentence+sentence_index
  217. value_begin_sentence = get_sentence_index(list_sent_span,_d["position"]["value_begin_sentence_start"])
  218. _d["position"]["value_begin_sentence"] = value_begin_sentence+sentence_index
  219. value_end_sentence = get_sentence_index(list_sent_span,_d["position"]["value_end_sentence_end"])
  220. _d["position"]["value_end_sentence"] = value_end_sentence+sentence_index
  221. return sentence_index + len(list_sentence)
  222. return sentence_index
  223. def tree_reposition(tree,sentence_index=None):
  224. if sentence_index is None:
  225. sentence_index = 0
  226. wordOffset_begin = 0
  227. wordOffset_end = 0
  228. for obj in tree:
  229. is_table = True if obj.get("tag","")=="table" else False
  230. if not is_table:
  231. sentence_index += 1
  232. obj["sentence_index"] = sentence_index
  233. obj["sentences"] = [obj.get("text","")]
  234. for _t in obj["sentences"]:
  235. wordOffset_end += len(_t)
  236. obj["wordOffset_begin"] = wordOffset_begin
  237. obj["wordOffset_end"] = wordOffset_end
  238. wordOffset_begin = wordOffset_end
  239. list_kv = obj.get("kv",[])
  240. for _d in list_kv:
  241. _d["position"]["key_begin_sentence"] = sentence_index
  242. _d["position"]["key_end_sentence"] = sentence_index
  243. _d["position"]["value_begin_sentence"] = sentence_index
  244. _d["position"]["value_end_sentence"] = sentence_index
  245. else:
  246. sentence_index += 1
  247. obj["sentence_index"] = sentence_index
  248. obj["sentence_index_start"] = sentence_index
  249. obj["sentences"] = [obj.get("text","")]
  250. sentence_index_end = update_table_position(obj,sentence_index)
  251. obj["sentence_index_end"] = sentence_index_end
  252. sentence_index = sentence_index_end
  253. for _t in obj["sentences"]:
  254. wordOffset_end += len(_t)
  255. obj["wordOffset_begin"] = wordOffset_begin
  256. obj["wordOffset_end"] = wordOffset_end
  257. wordOffset_begin = wordOffset_end
  258. # 递归地将 DOM 转换为 JSON
  259. def dom_to_tree(node):
  260. if node.name: # 如果是标签节点
  261. json_obj = DotDict({"tag": node.name})
  262. if node.attrs:
  263. json_obj["attributes"] = node.attrs
  264. is_table = False
  265. if node.name in ("table","tbody"):
  266. json_obj = table_to_tree(node)
  267. is_table = True
  268. if not is_table:
  269. children = []
  270. for child in node.contents:
  271. _child = dom_to_tree(child)
  272. if _child is not None:
  273. children.append(_child)
  274. if children:
  275. json_obj["children"] = children
  276. json_obj["name"] = json_obj.get("tag")
  277. return json_obj
  278. elif node.string and node.string.strip(): # 如果是纯文本节点
  279. _text = node.string.strip()
  280. _text = re.sub('\xa0','',_text)
  281. list_text = re.split("\s",_text)
  282. _text = ""
  283. for _t in list_text:
  284. if len(_t)<3:
  285. if len(_t)>0:
  286. _text += _t
  287. else:
  288. _text += _t+" "
  289. _text = _text.strip()
  290. return DotDict({"tag":"text","name":"text","text": _text})
  291. return None # 忽略空白字符
  292. def tree_pop_parent(tree):
  293. if isinstance(tree,list):
  294. for child in tree:
  295. tree_pop_parent(child)
  296. if isinstance(tree,dict):
  297. if "parent" in tree:
  298. del tree["parent"]
  299. for child in tree.get("children",[]):
  300. tree_pop_parent(child)
  301. def html_to_tree(html_content):
  302. # 使用 BeautifulSoup 解析 HTML
  303. soup = BeautifulSoup(html_content, "lxml")
  304. dom_tree = dom_to_tree(soup)
  305. extract_kv_from_tree(dom_tree)
  306. list_objs = get_outobjs_from_tree(dom_tree)
  307. tree_reposition(list_objs)
  308. return dom_tree
  309. def print_tree(dom_tree):
  310. # 转换为 JSON 格式
  311. tree_pop_parent(dom_tree)
  312. json_output = json.dumps(dom_tree,ensure_ascii=False, indent=2)
  313. # kv_pattern = "\s*(?P<key>.{,10})[::]\s*(?P<value>[^::。,()]+?)(\s+|$|;|;)(?![\u4e00-\u9fa5]+:)"
  314. kv_pattern = r"(?P<key>[\u4e00-\u9fa5]+):\s*(?P<value>[^\s,。();;]+)"
  315. def get_kv_pattern():
  316. import re
  317. text = """
  318. name: John age: 30 note: invalid;
  319. """
  320. # 正则模式
  321. kv_pattern = r"(?P<key>[a-zA-Z]+)[::](?P<value>.+(?!.*[::]))"
  322. # 提取匹配
  323. matches = re.findall(kv_pattern, text)
  324. # 打印结果
  325. for match in matches:
  326. key, value = match
  327. print("{%s}: {%s}"%(key,value))
  328. def extract_kv_from_sentence(sentence):
  329. list_kv = []
  330. _iter = re.finditer("[::]", sentence)
  331. if _iter:
  332. list_span = []
  333. for iter in _iter:
  334. list_span.append(iter.span())
  335. if len(list_span)==1:
  336. _begin,_end = list_span[0]
  337. if _begin<20 and _end<len(sentence)-1:
  338. _d = DotDict({"key":sentence[0:_begin],"value":sentence[_end:]})
  339. _d["position"] = {"key_begin_sentence":0,
  340. "key_begin_sentence_start":0,
  341. "key_end_sentence":0,
  342. "key_end_sentence_end":_begin,
  343. "value_begin_sentence":0,
  344. "value_begin_sentence_start":_end,
  345. "value_end_sentence":0,
  346. "value_end_sentence_end":len(sentence)
  347. }
  348. list_kv.append(_d)
  349. else:
  350. _begin = 0
  351. _end = len(sentence)-1
  352. iter = re.search(kv_pattern,sentence[_begin:_end])
  353. if iter is not None:
  354. _d = DotDict({})
  355. _d["key"] = iter.group("key")
  356. _d["value"] = iter.group("value")
  357. _d["position"] = {"key_begin_sentence":0,
  358. "key_begin_sentence_start":iter.span("key")[0],
  359. "key_end_sentence":0,
  360. "key_end_sentence_end":iter.span("key")[0]+len(_d.get("key","")),
  361. "value_begin_sentence":0,
  362. "value_begin_sentence_start":iter.span("value")[0],
  363. "value_end_sentence":0,
  364. "value_end_sentence_end":iter.span("value")[0]+len(_d.get("value",""))
  365. }
  366. list_kv.append(_d)
  367. elif len(list_span)>1:
  368. _begin,_end = list_span[0]
  369. if _begin<20 and len(sentence)>100:
  370. _d = DotDict({"key":sentence[0:_begin],"value":sentence[_end:]})
  371. _d["position"] = {"key_begin_sentence":0,
  372. "key_begin_sentence_start":0,
  373. "key_end_sentence":0,
  374. "key_end_sentence_end":_begin,
  375. "value_begin_sentence":0,
  376. "value_begin_sentence_start":_end,
  377. "value_end_sentence":0,
  378. "value_end_sentence_end":len(sentence)
  379. }
  380. list_kv.append(_d)
  381. else:
  382. _begin = 0
  383. for _i in range(len(list_span)-1):
  384. _end = list_span[_i+1][0]
  385. iter = re.search(kv_pattern,sentence[_begin:_end])
  386. _begin = list_span[_i][1]
  387. if iter is not None:
  388. _d = DotDict({})
  389. _d["key"] = iter.group("key")
  390. _d["value"] = iter.group("value")
  391. _d["position"] = {"key_begin_sentence":0,
  392. "key_begin_sentence_start":iter.span("key")[0],
  393. "key_end_sentence":0,
  394. "key_end_sentence_end":iter.span("key")[0]+len(_d.get("key","")),
  395. "value_begin_sentence":0,
  396. "value_begin_sentence_start":iter.span("value")[0],
  397. "value_end_sentence":0,
  398. "value_end_sentence_end":iter.span("value")[0]+len(_d.get("value",""))
  399. }
  400. list_kv.append(_d)
  401. _begin = list_span[-2][1]
  402. _end = len(sentence)
  403. iter = re.search(kv_pattern,sentence[_begin:_end])
  404. if iter is not None:
  405. _d = DotDict({})
  406. _d["key"] = iter.group("key")
  407. _d["value"] = iter.group("value")
  408. _d["position"] = {"key_begin_sentence":0,
  409. "key_begin_sentence_start":iter.span("key")[0],
  410. "key_end_sentence":0,
  411. "key_end_sentence_end":iter.span("key")[0]+len(_d.get("key","")),
  412. "value_begin_sentence":0,
  413. "value_begin_sentence_start":iter.span("value")[0],
  414. "value_end_sentence":0,
  415. "value_end_sentence_end":iter.span("value")[0]+len(_d.get("value",""))
  416. }
  417. list_kv.append(_d)
  418. # for iter in _iter:
  419. # _d = DotDict({})
  420. # _d["key"] = iter.group("key")
  421. # _d["value"] = iter.group("value")
  422. # _d["key_span"] = iter.span("key")
  423. # _d["value_span"] = iter.span("value")
  424. # list_kv.append(_d)
  425. return list_kv
  426. def extract_kv_from_node(node):
  427. list_kv = []
  428. list_text = []
  429. childs = node.get("children",[])
  430. _text = ""
  431. has_br = False
  432. if childs:
  433. for child in childs:
  434. node_name = child.get("tag","")
  435. child_text = child.get("text")
  436. if node_name=="br":
  437. list_text.append([])
  438. has_br = True
  439. if child_text:
  440. if len(list_text)==0:
  441. list_text.append([])
  442. list_text[-1].append(child)
  443. node["kv"] = []
  444. if has_br:
  445. new_children = []
  446. for texts in list_text:
  447. if texts:
  448. _text = "".join([a.get("text") for a in texts])
  449. tag = texts[0]
  450. list_kv = extract_kv_from_sentence(_text)
  451. _n = DotDict({"tag":tag,"name":tag,"text":_text,"children":[],"kv":list_kv})
  452. new_children.append(_n)
  453. node["children"] = new_children
  454. else:
  455. for texts in list_text:
  456. _text = "".join([a.get("text") for a in texts])
  457. if _text:
  458. list_kv = extract_kv_from_sentence(_text)
  459. node["kv"].extend(list_kv)
  460. else:
  461. _text = node.get("text")
  462. if _text:
  463. list_kv = extract_kv_from_sentence(_text)
  464. node["kv"] = list_kv
  465. return list_kv
  466. def get_child_text(node):
  467. _text = node.get("text","")
  468. for child in node.get("children",[]):
  469. _text += get_child_text(child)
  470. return _text
  471. def extract_kv_from_tree(tree):
  472. if isinstance(tree,list):
  473. _count = 0
  474. has_table = False
  475. for child in tree:
  476. _c,_t = extract_kv_from_tree(child)
  477. _count += _c
  478. if _t:
  479. has_table = _t
  480. return _count,has_table
  481. if isinstance(tree,dict):
  482. if tree.get("tag","")!="table":
  483. childs = tree.get("children",[])
  484. if len(childs)>0:
  485. _count = 0
  486. has_table = False
  487. child_has_p_div = False
  488. child_has_br = False
  489. for child in childs:
  490. _c,_t = extract_kv_from_tree(child)
  491. _count += _c
  492. if _t:
  493. has_table = _t
  494. if child.get("tag","") in ("p","div","li"):
  495. child_has_p_div = True
  496. if child.get("tag","")=="br":
  497. child_has_br = True
  498. if _count==0:
  499. if not has_table and not child_has_p_div and not child_has_br:
  500. _text = get_child_text(tree)
  501. if "children" in tree:
  502. del tree["children"]
  503. tree["text"] = _text
  504. list_kv = extract_kv_from_node(tree)
  505. _count = len(list_kv)
  506. return _count,has_table
  507. if tree.get("tag","") in ("p","div","li") and not has_table and not child_has_p_div:
  508. if not child_has_br:
  509. _text = get_child_text(tree)
  510. tree["text"] = _text
  511. if "children" in tree:
  512. del tree["children"]
  513. p_list_kv = extract_kv_from_node(tree)
  514. return len(p_list_kv),has_table
  515. return _count,has_table
  516. else:
  517. list_kv = extract_kv_from_node(tree)
  518. return len(list_kv),False
  519. else:
  520. return len(tree.get("kv",[])),True
  521. return 0,False
  522. def update_kv_span(list_kv,append_length):
  523. for _d in list_kv:
  524. _d["position"] = {"key_begin_sentence":0,
  525. "key_begin_sentence_start":_d.get("key_sen_index",0),
  526. "key_end_sentence":0,
  527. "key_end_sentence_end":_d.get("key_sen_index",0)+len(_d.get("key","")),
  528. "value_begin_sentence":0,
  529. "value_begin_sentence_start":_d.get("value_sen_index",0),
  530. "value_end_sentence":0,
  531. "value_end_sentence_end":_d.get("value_sen_index",0)+len(_d.get("value",""))
  532. }
  533. _d["position"]["key_begin_sentence_start"] += append_length
  534. _d["position"]["key_end_sentence_end"] += append_length
  535. _d["position"]["value_begin_sentence_start"] += append_length
  536. _d["position"]["value_end_sentence_end"] += append_length
  537. def get_outobjs_from_tree(tree,list_outobjs=None):
  538. is_first = False
  539. if list_outobjs is None:
  540. list_outobjs = []
  541. is_first = True
  542. if isinstance(tree,list):
  543. for child in tree:
  544. get_outobjs_from_tree(child,list_outobjs)
  545. if isinstance(tree,dict):
  546. childs = tree.get("children",[])
  547. _text = tree.get("text","")
  548. is_table = True if tree.get("tag","")=="table" else False
  549. if is_table:
  550. if _text!="" and _text is not None:
  551. tree.name = tree.tag
  552. list_outobjs.append(tree)
  553. else:
  554. for child in childs:
  555. get_outobjs_from_tree(child,list_outobjs)
  556. else:
  557. if _text!="" and _text is not None:
  558. tree.name = tree.tag
  559. tree.text = _text
  560. list_outobjs.append(tree)
  561. for child in childs:
  562. get_outobjs_from_tree(child,list_outobjs)
  563. return list_outobjs
  564. def standard_title_context(_title_context):
  565. return _title_context.replace("(","(").replace(")",")").replace(":",":").replace(":",";").replace(",",".").replace(",",".").replace("、",".").replace(".",".")
  566. def standard_product(sentence):
  567. return sentence.replace("(","(").replace(")",")")
  568. import Levenshtein
  569. import copy
  570. def jaccard_score(source,target):
  571. source_set = set([s for s in source])
  572. target_set = set([s for s in target])
  573. if len(source_set)==0 or len(target_set)==0:
  574. return 0
  575. return max(len(source_set&target_set)/len(source_set),len(source_set&target_set)/len(target_set))
  576. def judge_pur_chinese(keyword):
  577. """
  578. 中文字符的编码范围为: u'\u4e00' -- u'\u9fff:只要在此范围内就可以判断为中文字符串
  579. @param keyword:
  580. @return:
  581. """
  582. # 定义一个需要删除的标点符号字符串列表
  583. remove_chars = '[·’!"\#$%&\'()#!()*+,-./:;<=>?\@,:?¥★、….>【】[]《》?“”‘’\[\\]^_`{|}~]+'
  584. # 利用re.sub来删除中文字符串中的标点符号
  585. strings = re.sub(remove_chars, "", keyword) # 将keyword中文字符串中remove_chars中包含的标点符号替换为空字符串
  586. for ch in strings:
  587. if u'\u4e00' <= ch <= u'\u9fff':
  588. pass
  589. else:
  590. return False
  591. return True
  592. def is_similar(source,target,_radio=None):
  593. source = str(source).lower()
  594. target = str(target).lower()
  595. max_len = max(len(source),len(target))
  596. min_len = min(len(source),len(target))
  597. min_ratio = 90
  598. if min_len>=3:
  599. min_ratio = 87
  600. if min_len>=5:
  601. min_ratio = 85
  602. if _radio is not None:
  603. min_ratio = _radio
  604. # dis_len = abs(len(source)-len(target))
  605. # min_dis = min(max_len*0.2,4)
  606. if min_len==0 and max_len>0:
  607. return False
  608. if max_len<=2:
  609. if source==target:
  610. return True
  611. if min_len<2:
  612. return False
  613. #判断相似度
  614. similar = Levenshtein.ratio(source,target)*100
  615. if similar>=min_ratio:
  616. log("%s and %s similar_jaro %d"%(source,target,similar))
  617. return True
  618. similar_jaro = Levenshtein.jaro(source,target)
  619. if similar_jaro*100>=min_ratio:
  620. log("%s and %s similar_jaro %d"%(source,target,similar_jaro*100))
  621. return True
  622. similar_jarow = Levenshtein.jaro_winkler(source,target)
  623. if similar_jarow*100>=min_ratio:
  624. log("%s and %s similar_jaro %d"%(source,target,similar_jarow*100))
  625. return True
  626. if min_len>=5:
  627. if len(source)==max_len and str(source).find(target)>=0:
  628. return True
  629. elif len(target)==max_len and target.find(source)>=0:
  630. return True
  631. elif jaccard_score(source, target)==1 and judge_pur_chinese(source) and judge_pur_chinese(target):
  632. return True
  633. return False
  634. end_pattern = "商务要求|评分标准|商务条件|商务条件"
  635. _param_pattern = "(产品|技术|清单|配置|参数|具体|明细|项目|招标|货物|服务|规格|工作|具体)[及和与]?(指标|配置|条件|要求|参数|需求|规格|条款|名称及要求)|配置清单|(质量|技术).{,10}要求|验收标准|^(参数|功能)$"
  636. meter_pattern = "[><≤≥±]\d+|\d+(?:[μucmkK微毫千]?[米升LlgGmMΩ]|摄氏度|英寸|度|天|VA|dB|bpm|rpm|kPa|mol|cmH20|%|°|Mpa|Hz|K?HZ|℃|W|min|[*×xX])|[*×xX]\d+|/min|\ds[^a-zA-Z]|GB.{,20}标准|PVC|PP|角度|容积|色彩|自动|流量|外径|轴位|折射率|帧率|柱镜|振幅|磁场|镜片|防漏|强度|允差|心率|倍数|瞳距|底座|色泽|噪音|间距|材质|材料|表面|频率|阻抗|浓度|兼容|防尘|防水|内径|实时|一次性|误差|性能|距离|精确|温度|超温|范围|跟踪|对比度|亮度|[横纵]向|均压|负压|正压|可调|设定值|功能|检测|高度|厚度|宽度|深度|[单双多]通道|效果|指数|模式|尺寸|重量|峰值|谷值|容量|寿命|稳定性|高温|信号|电源|电流|转换率|效率|释放量|转速|离心力|向心力|弯曲|电压|功率|气量|国标|标准协议|灵敏度|最大值|最小值|耐磨|波形|高压|性强|工艺|光源|低压|压力|压强|速度|湿度|重量|毛重|[MLX大中小]+码|净重|颜色|[红橙黄绿青蓝紫]色|不锈钢|输入|输出|噪声|认证|配置"
  637. not_meter_pattern = "投标报价|中标金额|商务部分|公章|分值构成|业绩|详见|联系人|联系电话|合同价|金额|采购预算|资金来源|费用|质疑|评审因素|评审标准|商务资信|商务评分|专家论证意见|评标方法|代理服务费|售后服务|评分类型|评分项目|预算金额|得\d+分|项目金额|详见招标文件|乙方"
  638. def getTrs(tbody):
  639. #获取所有的tr
  640. trs = []
  641. if tbody.name=="table":
  642. body = tbody.find("tbody",recursive=False)
  643. if body is not None:
  644. tbody = body
  645. objs = tbody.find_all(recursive=False)
  646. for obj in objs:
  647. if obj.name=="tr":
  648. trs.append(obj)
  649. if obj.name=="tbody" or obj.name=="table":
  650. for tr in obj.find_all("tr",recursive=False):
  651. trs.append(tr)
  652. return trs
  653. def fixSpan(tbody):
  654. # 处理colspan, rowspan信息补全问题
  655. #trs = tbody.findChildren('tr', recursive=False)
  656. trs = getTrs(tbody)
  657. ths_len = 0
  658. ths = list()
  659. trs_set = set()
  660. #修改为先进行列补全再进行行补全,否则可能会出现表格解析混乱
  661. # 遍历每一个tr
  662. for indtr, tr in enumerate(trs):
  663. ths_tmp = tr.findChildren('th', recursive=False)
  664. #不补全含有表格的tr
  665. if len(tr.findChildren('table'))>0:
  666. continue
  667. if len(ths_tmp) > 0:
  668. ths_len = ths_len + len(ths_tmp)
  669. for th in ths_tmp:
  670. ths.append(th)
  671. trs_set.add(tr)
  672. # 遍历每行中的element
  673. tds = tr.findChildren(recursive=False)
  674. for indtd, td in enumerate(tds):
  675. # 若有colspan 则补全同一行下一个位置
  676. if 'colspan' in td.attrs:
  677. if str(re.sub("[^0-9]","",str(td['colspan'])))!="":
  678. col = int(re.sub("[^0-9]","",str(td['colspan'])))
  679. if col<100 and len(td.get_text())<1000:
  680. td['colspan'] = 1
  681. for i in range(1, col, 1):
  682. td.insert_after(copy.copy(td))
  683. for indtr, tr in enumerate(trs):
  684. ths_tmp = tr.findChildren('th', recursive=False)
  685. #不补全含有表格的tr
  686. if len(tr.findChildren('table'))>0:
  687. continue
  688. if len(ths_tmp) > 0:
  689. ths_len = ths_len + len(ths_tmp)
  690. for th in ths_tmp:
  691. ths.append(th)
  692. trs_set.add(tr)
  693. # 遍历每行中的element
  694. tds = tr.findChildren(recursive=False)
  695. for indtd, td in enumerate(tds):
  696. # 若有rowspan 则补全下一行同样位置
  697. if 'rowspan' in td.attrs:
  698. if str(re.sub("[^0-9]","",str(td['rowspan'])))!="":
  699. row = int(re.sub("[^0-9]","",str(td['rowspan'])))
  700. td['rowspan'] = 1
  701. for i in range(1, row, 1):
  702. # 获取下一行的所有td, 在对应的位置插入
  703. if indtr+i<len(trs):
  704. tds1 = trs[indtr + i].findChildren(['td','th'], recursive=False)
  705. if len(tds1) >= (indtd) and len(tds1)>0:
  706. if indtd > 0:
  707. tds1[indtd - 1].insert_after(copy.copy(td))
  708. else:
  709. tds1[0].insert_before(copy.copy(td))
  710. elif indtd-2>0 and len(tds1) > 0 and len(tds1) == indtd - 1: # 修正某些表格最后一列没补全
  711. tds1[indtd-2].insert_after(copy.copy(td))
  712. def getTable(tbody):
  713. #trs = tbody.findChildren('tr', recursive=False)
  714. fixSpan(tbody)
  715. trs = getTrs(tbody)
  716. inner_table = []
  717. for tr in trs:
  718. tr_line = []
  719. tds = tr.findChildren(['td','th'], recursive=False)
  720. if len(tds)==0:
  721. tr_line.append([re.sub('\xa0','',tr.get_text()),0]) # 2021/12/21 修复部分表格没有td 造成数据丢失
  722. for td in tds:
  723. tr_line.append([re.sub('\xa0','',td.get_text()),0])
  724. #tr_line.append([td.get_text(),0])
  725. inner_table.append(tr_line)
  726. return inner_table
  727. def extract_products(list_data,_product,_param_pattern = "产品名称|设备材料|采购内存|标的名称|采购内容|(标的|维修|系统|报价构成|商品|产品|物料|物资|货物|设备|采购品|采购条目|物品|材料|印刷品?|采购|物装|配件|资产|耗材|清单|器材|仪器|器械|备件|拍卖物|标的物|物件|药品|药材|药械|货品|食品|食材|品目|^品名|气体|标项|分项|项目|计划|包组|标段|[分子]?包|子目|服务|招标|中标|成交|工程|招标内容)[\))的]?([、\w]{,4}名称|内容|描述)|标的|标项|项目$|商品|产品|物料|物资|货物|设备|采购品|采购条目|物品|材料|印刷品|物装|配件|资产|招标内容|耗材|清单|器材|仪器|器械|备件|拍卖物|标的物|物件|药品|药材|药械|货品|食品|食材|菜名|^品目$|^品名$|^名称|^内容$"):
  728. _product = standard_product(_product)
  729. list_result = []
  730. list_table_products = []
  731. for _data_i in range(len(list_data)):
  732. _data = list_data[_data_i]
  733. _type = _data["type"]
  734. _text = _data["text"]
  735. if _type=="table":
  736. list_table = _data["list_table"]
  737. if list_table is None:
  738. continue
  739. _check = True
  740. max_length = max([len(a) for a in list_table])
  741. min_length = min([len(a) for a in list_table])
  742. if min_length<max_length/2:
  743. continue
  744. list_head_index = []
  745. _begin_index = 0
  746. head_cell_text = ""
  747. for line_i in range(len(list_table[:2])):
  748. line = list_table[line_i]
  749. line_text = ",".join([cell[0] for cell in line])
  750. for cell_i in range(len(line)):
  751. cell = line[cell_i]
  752. cell_text = cell[0]
  753. if len(cell_text)<10 and re.search(_param_pattern,cell_text) is not None and re.search("单价|数量|预算|限价|总价|品牌|规格|型号|用途|要求|采购量",line_text) is not None:
  754. _begin_index = line_i+1
  755. list_head_index.append(cell_i)
  756. for line_i in range(len(list_table)):
  757. line = list_table[line_i]
  758. for cell_i in list_head_index:
  759. if cell_i>=len(line):
  760. continue
  761. cell = line[cell_i]
  762. cell_text = cell[0]
  763. head_cell_text += cell_text
  764. # print("===head_cell_text",head_cell_text)
  765. if re.search("招标人|采购人|项目编号|项目名称|金额|^\d+$",head_cell_text) is not None:
  766. list_head_index = []
  767. for line in list_table:
  768. line_text = ",".join([cell[0] for cell in line])
  769. for cell_i in range(len(line)):
  770. cell = line[cell_i]
  771. cell_text = cell[0]
  772. if cell_text is not None and _product is not None and len(cell_text)<len(_product)*10 and cell_text.find(_product)>=0 and re.search("单价|数量|总价|规格|品牌|型号|用途|要求|采购量",line_text) is not None:
  773. list_head_index.append(cell_i)
  774. list_head_index = list(set(list_head_index))
  775. if len(list_head_index)>0:
  776. has_number = False
  777. for cell_i in list_head_index:
  778. table_products = []
  779. for line_i in range(_begin_index,len(list_table)):
  780. line = list_table[line_i]
  781. for _i in range(len(line)):
  782. cell = line[_i]
  783. cell_text = cell[0]
  784. if re.search("^\d+$",cell_text) is not None:
  785. has_number = True
  786. if cell_i>=len(line):
  787. continue
  788. cell = line[cell_i]
  789. cell_text = cell[0]
  790. if re.search(_param_pattern,cell_text) is None or has_number:
  791. if re.search("^[\da-zA-Z]+$",cell_text) is None:
  792. table_products.append(cell_text)
  793. if len(table_products)>0:
  794. logger.debug("table products %s"%(str(table_products)))
  795. if min([len(x) for x in table_products])>0 and max([len(x) for x in table_products])<=30:
  796. if re.search("招标人|代理人|预算|数量|交货期|品牌|产地","".join(table_products)) is None:
  797. list_table_products.append(table_products)
  798. _find = False
  799. for table_products in list_table_products:
  800. for _p in table_products:
  801. if is_similar(_product,_p,90):
  802. _find = True
  803. logger.debug("similar table_products %s"%(str(table_products)))
  804. list_result = list(set([a for a in table_products if len(a)>1 and len(a)<20 and re.search("费用|预算|合计|金额|万元|运费|^其他$",a) is None]))
  805. break
  806. if not _find:
  807. for table_products in list_table_products:
  808. list_result.extend(table_products)
  809. list_result = list(set([a for a in list_result if len(a)>1 and len(a)<30 and re.search("费用|预算|合计|金额|万元|运费",a) is None]))
  810. return list_result
  811. def get_childs(childs, max_depth=None):
  812. list_data = []
  813. for _child in childs:
  814. list_data.append(_child)
  815. childs2 = _child.get("child_title",[])
  816. if len(childs2)>0 and (max_depth==None or max_depth>0):
  817. for _child2 in childs2:
  818. if max_depth != None:
  819. list_data.extend(get_childs([_child2], max_depth-1))
  820. else:
  821. list_data.extend(get_childs([_child2], None))
  822. return list_data
  823. class Html2KVTree():
  824. def __init__(self,_html,auto_merge_table=True,list_obj = []):
  825. if _html is None:
  826. _html = ""
  827. self.html = _html
  828. self.auto_merge_table = auto_merge_table
  829. if list_obj:
  830. self.list_obj = list_obj
  831. else:
  832. _tree = html_to_tree(_html)
  833. self.list_obj = get_outobjs_from_tree(_tree)
  834. # for obj in self.list_obj:
  835. # print("obj",obj.get_text()[:20])
  836. self.tree = self.buildParsetree(self.list_obj,[],auto_merge_table)
  837. # #识别目录树
  838. # self.print_tree(self.tree,"-|")
  839. def get_soup_objs(self,soup,list_obj=None):
  840. if list_obj is None:
  841. list_obj = []
  842. childs = soup.find_all(recursive=False)
  843. for _obj in childs:
  844. childs1 = _obj.find_all(recursive=False)
  845. if len(childs1)==0 or len(_obj.get_text())<40 or _obj.name=="table":
  846. list_obj.append(_obj)
  847. elif _obj.name=="p":
  848. list_obj.append(_obj)
  849. else:
  850. self.get_soup_objs(_obj,list_obj)
  851. return list_obj
  852. def fix_tree(self,_product):
  853. products = extract_products(self.tree,_product)
  854. if len(products)>0:
  855. self.tree = self.buildParsetree(self.list_obj,products,self.auto_merge_table)
  856. def print_tree(self,tree,append="",set_tree_id=None):
  857. if set_tree_id is None:
  858. set_tree_id = set()
  859. if append=="":
  860. for t in tree:
  861. logger.debug("%s text:%s title:%s title_text:%s before:%s after%s product:%s"%("==>",t["text"][:50],t["sentence_title"],t["sentence_title_text"],t["title_before"],t["title_after"],t["has_product"]))
  862. for t in tree:
  863. _id = id(t)
  864. if _id in set_tree_id:
  865. continue
  866. set_tree_id.add(_id)
  867. logger.info("%s text:%s title:%s title_text:%s before:%s after%s product:%s kv:%s"%(append,t["text"][:50],t["sentence_title"],t["sentence_title_text"],t["title_before"],t["title_after"],t["has_product"],str(t["kv"])))
  868. childs = t["child_title"]
  869. self.print_tree(childs,append=append+"-|",set_tree_id=set_tree_id)
  870. def is_title_first(self,title):
  871. if title in ("一","1","Ⅰ","a","A"):
  872. return True
  873. return False
  874. def find_title_by_pattern(self,_text,_pattern="(^|★|▲|:|:|\s+)(?P<title_1>(?P<title_1_index_0_0>第?)(?P<title_1_index_1_1>[一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+)(?P<title_1_index_2_0>[、章册包标部.::]+))|" \
  875. "([\s★▲\*]*)(?P<title_3>(?P<title_3_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?)(?P<title_3_index_0_1>[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+)(?P<title_3_index_0_2>[、章册包标部.::]+))|" \
  876. "([\s★▲\*]*)(?P<title_4>(?P<title_4_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?第?)(?P<title_4_index_1_1>[一二三四五六七八九十]+)(?P<title_4_index_2_0>[节章册部\.::、、]+))|" \
  877. "([\s★▲\*]*)(?P<title_5>(?P<title_5_index_0_0>^)(?P<title_5_index_1_1>[一二三四五六七八九十]+)(?P<title_5_index_2_0>)[^一二三四五六七八九十节章册部\.::、])|" \
  878. "([\s★▲\*]*)(?P<title_12>(?P<title_12_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?\d{1,2}[\..、\s\-]\d{1,2}[\..、\s\-]\d{1,2}[\..、\s\-]\d{1,2}[\..、\s\-])(?P<title_12_index_1_1>\d{1,2})(?P<title_12_index_2_0>[\..、\s\-]?))|"\
  879. "([\s★▲\*]*)(?P<title_11>(?P<title_11_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?\d{1,2}[\..、\s\-]\d{1,2}[\..、\s\-]\d{1,2}[\..、\s\-])(?P<title_11_index_1_1>\d{1,2})(?P<title_11_index_2_0>[\..、\s\-]?))|" \
  880. "([\s★▲\*]*)(?P<title_10>(?P<title_10_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?\d{1,2}[\..、\s\-]\d{1,2}[\..、\s\-])(?P<title_10_index_1_1>\d{1,2})(?P<title_10_index_2_0>[\..、\s\-]?))|" \
  881. "([\s★▲\*]*)(?P<title_7>(?P<title_7_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?\d{1,2}[\..\s\-])(?P<title_7_index_1_1>\d{1,2})(?P<title_7_index_2_0>[\..包标::、\s\-]*))|" \
  882. "(^[\s★▲\*]*)(?P<title_6>(?P<title_6_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?包?)(?P<title_6_index_0_1>\d{1,2})(?P<title_6_index_2_0>[\..、\s\-包标]*))|" \
  883. "([\s★▲\*]*)(?P<title_15>(?P<title_15_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?[((]?)(?P<title_15_index_1_1>\d{1,2})(?P<title_15_index_2_0>[))包标\..::、]+))|" \
  884. "([\s★▲\*]+)(?P<title_17>(?P<title_17_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?[((]?)(?P<title_17_index_1_1>[a-zA-Z]+)(?P<title_17_index_2_0>[))包标\..::、]+))|" \
  885. "([\s★▲\*]*)(?P<title_19>(?P<title_19_index_0_0>[^一二三四五六七八九十\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]{,3}?[((]?)(?P<title_19_index_1_1>[一二三四五六七八九十ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+)(?P<title_19_index_2_0>[))]))"
  886. ):
  887. _se = re.search(_pattern,_text)
  888. groups = []
  889. if _se is not None:
  890. e = _se.end()
  891. if re.search('(时间|日期|编号|账号|号码|手机|价格|\w价|人民币|金额|得分|分值|总分|满分|最高得|扣|减|数量|评委)[::]?\d', _se.group(0)) or (re.search('\d[.::]?$', _se.group(0)) and re.search('^[\d年月日万元天个分秒台条A-Za-z]|^(小时)', _text[e:])):
  892. return None
  893. elif re.match('[二三四五六七八九十]\w{1,2}[市区县]|五金|四川|八疆|九龙|[一二三四五六七八九十][层天标包]', _text) and re.match('[一二三四五六七八九十]', _se.group(0)): # 289765335 排除三明市等开头作为大纲
  894. return None
  895. elif re.search('^[\u4e00-\u9fa5]+[::]', _text[:e]):
  896. return None
  897. _gd = _se.groupdict()
  898. for k,v in _gd.items():
  899. if v is not None:
  900. groups.append((k,v))
  901. if len(groups):
  902. groups.sort(key=lambda x:x[0])
  903. return groups
  904. return None
  905. def make_increase(self,_sort,_title,_add=1):
  906. if len(_title)==0 and _add==0:
  907. return ""
  908. if len(_title)==0 and _add==1:
  909. return _sort[0]
  910. _index = _sort.index(_title[-1])
  911. next_index = (_index+_add)%len(_sort)
  912. next_chr = _sort[next_index]
  913. if _index==len(_sort)-1:
  914. _add = 1
  915. else:
  916. _add = 0
  917. return next_chr+self.make_increase(_sort,_title[:-1],_add)
  918. def get_next_title(self,_title):
  919. if re.search("^\d+$",_title) is not None:
  920. return str(int(_title)+1)
  921. if re.search("^[一二三四五六七八九十百]+$",_title) is not None:
  922. if _title[-1]=="十":
  923. return _title+"一"
  924. if _title[-1]=="百":
  925. return _title+"零一"
  926. if _title[-1]=="九":
  927. if len(_title)==1:
  928. return "十"
  929. if len(_title)==2:
  930. if _title[0]=="十":
  931. return "二十"
  932. if len(_title)==3:
  933. if _title[0]=="九":
  934. return "一百"
  935. else:
  936. _next_title = self.make_increase(['一','二','三','四','五','六','七','八','九','十'],re.sub("[十百]",'',_title[0]))
  937. return _next_title+"十"
  938. _next_title = self.make_increase(['一','二','三','四','五','六','七','八','九','十'],re.sub("[十百]",'',_title))
  939. _next_title = list(_next_title)
  940. _next_title.reverse()
  941. if _next_title[-1]!="十":
  942. if len(_next_title)>=2:
  943. _next_title.insert(-1,'十')
  944. if len(_next_title)>=4:
  945. _next_title.insert(-3,'百')
  946. if _title[0]=="十":
  947. if _next_title=="十":
  948. _next_title = ["二","十"]
  949. _next_title.insert(0,"十")
  950. _next_title = "".join(_next_title)
  951. return _next_title
  952. if re.search("^[a-z]+$",_title) is not None:
  953. _next_title = self.make_increase([chr(i+ord('a')) for i in range(26)],_title)
  954. _next_title = list(_next_title)
  955. _next_title.reverse()
  956. return "".join(_next_title)
  957. if re.search("^[A-Z]+$",_title) is not None:
  958. _next_title = self.make_increase([chr(i+ord('A')) for i in range(26)],_title)
  959. _next_title = list(_next_title)
  960. _next_title.reverse()
  961. return "".join(_next_title)
  962. if re.search("^[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]$",_title) is not None:
  963. _sort = ["Ⅰ","Ⅱ","Ⅲ","Ⅳ","Ⅴ","Ⅵ","Ⅶ","Ⅷ","Ⅸ","Ⅹ","Ⅺ","Ⅻ"]
  964. _index = _sort.index(_title)
  965. if _index<len(_sort)-1:
  966. return _sort[_index+1]
  967. return None
  968. def count_title_before(self,list_obj):
  969. dict_before = {}
  970. dict_sentence_count = {}
  971. illegal_sentence = set()
  972. for obj_i in range(len(list_obj)):
  973. obj = list_obj[obj_i]
  974. _type = "sentence"
  975. _text = obj.text.strip() if "text" in obj else ""
  976. if obj.name=="table":
  977. _type = "table"
  978. _text = str(obj)
  979. _append = False
  980. if _type=="sentence":
  981. if len(_text)>10 and len(_text)<100:
  982. if _text not in dict_sentence_count:
  983. dict_sentence_count[_text] = 0
  984. dict_sentence_count[_text] += 1
  985. if re.search("\d+页",_text) is not None:
  986. illegal_sentence.add(_text)
  987. elif len(_text)<10:
  988. if re.search("第\d+页",_text) is not None:
  989. illegal_sentence.add(_text)
  990. sentence_groups = self.find_title_by_pattern(_text[:10])
  991. if sentence_groups:
  992. # c062f53cf83401e671822003d63c1828print("sentence_groups",sentence_groups)
  993. sentence_title = sentence_groups[0][0]
  994. sentence_title_text = sentence_groups[0][1]
  995. title_index = sentence_groups[-2][1]
  996. title_before = sentence_groups[1][1].replace("(","(").replace(":",":").replace(":",";").replace(",",".").replace(",",".").replace("、",".")
  997. title_after = sentence_groups[-1][1].replace(")",")").replace(":",":").replace(":",";").replace(",",".").replace(",",".").replace("、",".")
  998. next_index = self.get_next_title(title_index)
  999. if title_before not in dict_before:
  1000. dict_before[title_before] = 0
  1001. dict_before[title_before] += 1
  1002. for k,v in dict_sentence_count.items():
  1003. if v>10:
  1004. illegal_sentence.add(k)
  1005. return dict_before,illegal_sentence
  1006. def is_page_no(self,sentence):
  1007. if len(sentence)<10:
  1008. if re.search("\d+页|^\-\d+\-$",sentence) is not None:
  1009. return True
  1010. def block_tree(self,childs):
  1011. for child in childs:
  1012. if not child["block"]:
  1013. child["block"] = True
  1014. childs2 = child["child_title"]
  1015. self.block_tree(childs2)
  1016. def buildParsetree(self,list_obj,products=[],auto_merge_table=True,auto_append=False):
  1017. self.parseTree = None
  1018. trees = []
  1019. list_length = []
  1020. for obj in list_obj[:200]:
  1021. if obj.name!="table":
  1022. list_length.append(len(obj.text))
  1023. if len(list_length)>0:
  1024. max_length = max(list_length)
  1025. else:
  1026. max_length = 40
  1027. max_length = min(max_length,40)
  1028. logger.debug("%s:%d"%("max_length",max_length))
  1029. list_data = []
  1030. last_table_index = None
  1031. last_table_columns = None
  1032. last_table = None
  1033. dict_before,illegal_sentence = self.count_title_before(list_obj)
  1034. for obj_i in range(len(list_obj)):
  1035. obj = list_obj[obj_i]
  1036. # logger.debug("==obj %s"%obj.text[:20])
  1037. _type = "sentence"
  1038. _text = standard_product(obj.text)
  1039. if obj.name=="table":
  1040. _type = "table"
  1041. _text = standard_product(str(obj))
  1042. _append = False
  1043. sentence_title = None
  1044. sentence_title_text = None
  1045. sentence_groups = None
  1046. title_index = None
  1047. next_index = None
  1048. parent_title = None
  1049. title_before = None
  1050. title_after = None
  1051. title_next = None
  1052. childs = []
  1053. # new
  1054. sentence_index = obj.sentence_index
  1055. wordOffset_begin = obj.wordOffset_begin
  1056. wordOffset_end = obj.wordOffset_end
  1057. sentences = obj.sentences
  1058. list_kv = obj.get("kv",[])
  1059. table_id = obj.get("table_id")
  1060. list_table = None
  1061. block = False
  1062. has_product = False
  1063. position = obj.get("position",{})
  1064. if _type=="sentence":
  1065. if _text in illegal_sentence:
  1066. continue
  1067. sentence_groups = self.find_title_by_pattern(_text[:10])
  1068. if sentence_groups:
  1069. title_before = standard_title_context(sentence_groups[1][1])
  1070. title_after = sentence_groups[-1][1]
  1071. sentence_title_text = sentence_groups[0][1]
  1072. other_text = _text.replace(sentence_title_text,"")
  1073. if (title_before in dict_before and dict_before[title_before]>1) or title_after!="":
  1074. sentence_title = sentence_groups[0][0]
  1075. title_index = sentence_groups[-2][1]
  1076. next_index = self.get_next_title(title_index)
  1077. other_text = _text.replace(sentence_title_text,"")
  1078. for p in products:
  1079. if other_text.strip()==p.strip():
  1080. has_product = True
  1081. else:
  1082. _fix = False
  1083. for p in products:
  1084. if other_text.strip()==p.strip():
  1085. title_before = "=产品"
  1086. sentence_title = "title_0"
  1087. sentence_title_text = p
  1088. title_index = "0"
  1089. title_after = "产品="
  1090. next_index = "0"
  1091. _fix = True
  1092. has_product = True
  1093. break
  1094. if not _fix:
  1095. title_before = None
  1096. title_after = None
  1097. sentence_title_text = None
  1098. else:
  1099. if len(_text)<40 and re.search(_param_pattern,_text) is not None:
  1100. for p in products:
  1101. if _text.find(p)>=0:
  1102. title_before = "=产品"
  1103. sentence_title = "title_0"
  1104. sentence_title_text = p
  1105. title_index = "0"
  1106. title_after = "产品="
  1107. next_index = "0"
  1108. _fix = True
  1109. has_product = True
  1110. break
  1111. # 合并两个非标题句子 20241106 注销,由于 485441521 招标内容结束位置不对
  1112. if auto_append:
  1113. if _type=="sentence":
  1114. if sentence_title is None and len(list_data)>0 and list_data[-1]["sentence_title"] is not None and list_data[-1]["line_width"]>=max_length*0.6:
  1115. list_data[-1]["text"] += _text
  1116. list_data[-1]["line_width"] = len(_text)
  1117. update_kv_span(list_kv,len(_text))
  1118. list_data[-1]["kv"].extend(list_kv)
  1119. list_data[-1]["sentences"].extend(sentences)
  1120. _append = True
  1121. elif sentence_title is None and len(list_data)>0 and _type==list_data[-1]["type"]:
  1122. if list_data[-1]["line_width"]>=max_length*0.7:
  1123. list_data[-1]["text"] += _text
  1124. list_data[-1]["line_width"] = len(_text)
  1125. update_kv_span(list_kv,len(_text))
  1126. list_data[-1]["kv"].extend(list_kv)
  1127. list_data[-1]["sentences"].extend(sentences)
  1128. _append = True
  1129. if not _append:
  1130. _data = {"type":_type,"tag":obj.get("tag"),"table_id":table_id, "text":_text,"sentences":sentences,"list_table":list_table,
  1131. "line_width":len(_text),"sentence_title":sentence_title,"title_index":title_index,
  1132. "sentence_title_text":sentence_title_text,"sentence_groups":sentence_groups,"parent_title":parent_title,
  1133. "child_title":childs,"title_before":title_before,"title_after":title_after,"title_next":title_next,"next_index":next_index,
  1134. "block":block,"has_product":has_product,
  1135. "sentence_index":sentence_index,"wordOffset_begin":wordOffset_begin,"wordOffset_end":wordOffset_end,
  1136. "kv":list_kv,"position":position
  1137. }
  1138. if sentence_title is not None:
  1139. if len(list_data)>0:
  1140. if self.is_title_first(title_index):
  1141. for i in range(1,len(list_data)+1):
  1142. _d = list_data[-i]
  1143. if _d["sentence_title"] is not None:
  1144. _data["parent_title"] = _d
  1145. _d["child_title"].append(_data)
  1146. break
  1147. else:
  1148. _find = False
  1149. for i in range(1,len(list_data)+1):
  1150. if _find:
  1151. break
  1152. _d = list_data[-i]
  1153. if _d.get("sentence_title")==sentence_title and title_before==_d["title_before"] and title_after==_d["title_after"]:
  1154. if _d["next_index"]==title_index and _d["title_next"] is None and not _d["block"]:
  1155. _data["parent_title"] = _d["parent_title"]
  1156. _d["title_next"] = _data
  1157. if len(_d["child_title"])>0:
  1158. _d["child_title"][-1]["title_next"] = ""
  1159. self.block_tree(_d["child_title"])
  1160. if _d["parent_title"] is not None:
  1161. _d["parent_title"]["child_title"].append(_data)
  1162. _find = True
  1163. break
  1164. for i in range(1,len(list_data)+1):
  1165. if _find:
  1166. break
  1167. _d = list_data[-i]
  1168. if i==1 and not _d["block"] and _d.get("sentence_title")==sentence_title and title_before==_d["title_before"] and title_after==_d["title_after"]:
  1169. _data["parent_title"] = _d["parent_title"]
  1170. _d["title_next"] = _data
  1171. if len(_d["child_title"])>0:
  1172. _d["child_title"][-1]["title_next"] = ""
  1173. self.block_tree(_d["child_title"])
  1174. if _d["parent_title"] is not None:
  1175. _d["parent_title"]["child_title"].append(_data)
  1176. _find = True
  1177. break
  1178. title_before = standard_title_context(title_before)
  1179. title_after = standard_title_context(title_after)
  1180. for i in range(1,len(list_data)+1):
  1181. if _find:
  1182. break
  1183. _d = list_data[-i]
  1184. if _d.get("sentence_title")==sentence_title and title_before==standard_title_context(_d["title_before"]) and title_after==standard_title_context(_d["title_after"]):
  1185. if _d["next_index"]==title_index and _d["title_next"] is None and not _d["block"]:
  1186. _data["parent_title"] = _d["parent_title"]
  1187. _d["title_next"] = _data
  1188. if len(_d["child_title"])>0:
  1189. _d["child_title"][-1]["title_next"] = ""
  1190. self.block_tree(_d["child_title"])
  1191. if _d["parent_title"] is not None:
  1192. _d["parent_title"]["child_title"].append(_data)
  1193. _find = True
  1194. break
  1195. for i in range(1,len(list_data)+1):
  1196. if _find:
  1197. break
  1198. _d = list_data[-i]
  1199. if not _d["block"] and _d.get("sentence_title")==sentence_title and title_before==standard_title_context(_d["title_before"]) and title_after==standard_title_context(_d["title_after"]):
  1200. _data["parent_title"] = _d["parent_title"]
  1201. _d["title_next"] = _data
  1202. if len(_d["child_title"])>0:
  1203. _d["child_title"][-1]["title_next"] = ""
  1204. # self.block_tree(_d["child_title"])
  1205. if _d["parent_title"] is not None:
  1206. _d["parent_title"]["child_title"].append(_data)
  1207. _find = True
  1208. break
  1209. for i in range(1,min(len(list_data)+1,20)):
  1210. if _find:
  1211. break
  1212. _d = list_data[-i]
  1213. if not _d["block"] and _d.get("sentence_title")==sentence_title and title_before==standard_title_context(_d["title_before"]):
  1214. _data["parent_title"] = _d["parent_title"]
  1215. _d["title_next"] = _data
  1216. if len(_d["child_title"])>0:
  1217. _d["child_title"][-1]["title_next"] = ""
  1218. # self.block_tree(_d["child_title"])
  1219. if _d["parent_title"] is not None:
  1220. _d["parent_title"]["child_title"].append(_data)
  1221. _find = True
  1222. break
  1223. if not _find:
  1224. if len(list_data)>0:
  1225. for i in range(1,len(list_data)+1):
  1226. _d = list_data[-i]
  1227. if _d.get("sentence_title") is not None:
  1228. _data["parent_title"] = _d
  1229. _d["child_title"].append(_data)
  1230. break
  1231. else:
  1232. if len(list_data)>0:
  1233. for i in range(1,len(list_data)+1):
  1234. _d = list_data[-i]
  1235. if _d.get("sentence_title") is not None:
  1236. _data["parent_title"] = _d
  1237. _d["child_title"].append(_data)
  1238. break
  1239. list_data.append(_data)
  1240. for _data in list_data:
  1241. childs = _data["child_title"]
  1242. for c_i in range(len(childs)):
  1243. cdata = childs[c_i]
  1244. if cdata["has_product"]:
  1245. continue
  1246. else:
  1247. if c_i>0:
  1248. last_cdata = childs[c_i-1]
  1249. if cdata["sentence_title"] is not None and last_cdata["sentence_title"] is not None and last_cdata["title_before"]==cdata["title_before"] and last_cdata["title_after"]==cdata["title_after"] and last_cdata["has_product"]:
  1250. cdata["has_product"] = True
  1251. if c_i<len(childs)-1:
  1252. last_cdata = childs[c_i+1]
  1253. if cdata["sentence_title"] is not None and last_cdata["sentence_title"] is not None and last_cdata["title_before"]==cdata["title_before"] and last_cdata["title_after"]==cdata["title_after"] and last_cdata["has_product"]:
  1254. cdata["has_product"] = True
  1255. for c_i in range(len(childs)):
  1256. cdata = childs[len(childs)-1-c_i]
  1257. if cdata["has_product"]:
  1258. continue
  1259. else:
  1260. if c_i>0:
  1261. last_cdata = childs[c_i-1]
  1262. if cdata["sentence_title"] is not None and last_cdata["sentence_title"] is not None and last_cdata["title_before"]==cdata["title_before"] and last_cdata["title_after"]==cdata["title_after"] and last_cdata["has_product"]:
  1263. cdata["has_product"] = True
  1264. if c_i<len(childs)-1:
  1265. last_cdata = childs[c_i+1]
  1266. if cdata["sentence_title"] is not None and last_cdata["sentence_title"] is not None and last_cdata["title_before"]==cdata["title_before"] and last_cdata["title_after"]==cdata["title_after"] and last_cdata["has_product"]:
  1267. cdata["has_product"] = True
  1268. return list_data
  1269. def get_tree_sentence(self):
  1270. list_sentence = []
  1271. for obj in self.tree:
  1272. list_sentence.extend(obj.get("sentences",[]))
  1273. return list_sentence
  1274. def extract_kvs_from_table(self,list_pattern,tree=None,result_kv=None):
  1275. if result_kv is None:
  1276. result_kv = [[] for i in list_pattern]
  1277. try:
  1278. for pattern in list_pattern:
  1279. re.compile(pattern)
  1280. except Exception as e:
  1281. log("list_pattern error: "+str(e))
  1282. return result_kv
  1283. if tree is None:
  1284. tree = self.tree
  1285. for obj in tree:
  1286. is_table = True if obj.get("tag","")=="table" else False
  1287. if is_table:
  1288. table_id = obj.get("table_id")
  1289. list_kv = obj.get("kv")
  1290. for _pi in range(len(list_pattern)):
  1291. table_kvs = []
  1292. for _d0 in list_kv:
  1293. _k = _d0.get("key","")
  1294. _v = _d0.get("value","")
  1295. _d = {"key":_k,"value":_v,"position":_d0.get("position",{}),
  1296. "key_row_index":_d0.get("key_row_index",0),"key_col_index":_d0.get("key_col_index",0),
  1297. "value_row_index":_d0.get("value_row_index",0),"value_col_index":_d0.get("value_col_index",0),}
  1298. if re.search(list_pattern[_pi],_k) is not None:
  1299. table_kvs.append(_d)
  1300. if table_kvs:
  1301. result_kv[_pi].append({"table_id":table_id,"kv":table_kvs})
  1302. childs = obj.get("children",[])
  1303. for child in childs:
  1304. self.extract_kvs_from_table(list_pattern,child,result_kv)
  1305. return result_kv
  1306. def extract_kvs_from_sentence(self,list_pattern,tree=None,result_kv=None):
  1307. if result_kv is None:
  1308. result_kv = [[] for i in list_pattern]
  1309. try:
  1310. for pattern in list_pattern:
  1311. re.compile(pattern)
  1312. except Exception as e:
  1313. log("list_pattern error: "+str(e))
  1314. return result_kv
  1315. if tree is None:
  1316. tree = self.tree
  1317. for obj in tree:
  1318. is_table = True if obj.get("tag","")=="table" else False
  1319. if not is_table:
  1320. list_kv = obj.get("kv",[])
  1321. for _pi in range(len(list_pattern)):
  1322. for _d in list_kv:
  1323. _k = _d.get("key","")
  1324. _v = _d.get("value","")
  1325. if re.search(list_pattern[_pi],_k) is not None:
  1326. result_kv[_pi].append(_d)
  1327. return result_kv
  1328. def extract_kvs_from_outline(self,list_pattern,tree=None,result_kv=None):
  1329. if result_kv is None:
  1330. result_kv = [[] for i in list_pattern]
  1331. try:
  1332. for pattern in list_pattern:
  1333. re.compile(pattern)
  1334. except Exception as e:
  1335. log("list_pattern error: "+str(e))
  1336. return result_kv
  1337. if tree is None:
  1338. tree = self.tree
  1339. for obj in tree:
  1340. is_table = True if obj.get("tag","")=="table" else False
  1341. if not is_table:
  1342. _text = obj["text"]
  1343. for _pi in range(len(list_pattern)):
  1344. sentence_index_from = obj["sentence_index"]
  1345. sentence_index_to = sentence_index_from
  1346. if re.search(list_pattern[_pi],_text) is not None and obj.get("sentence_title") is not None:
  1347. childs = get_childs([obj])
  1348. _child_text = ""
  1349. for _child in childs:
  1350. sentence_index_to = _child["sentence_index"]
  1351. _child_text+=_child["text"]+"\n"
  1352. result_kv[_pi].append({"key":_text,"value":_child_text,"from_outline":True,"key_sentence_index_from":sentence_index_from,
  1353. "key_sentence_index_to":sentence_index_from,"value_sentence_index_from":sentence_index_from,
  1354. "value_sentence_index_to":sentence_index_to,})
  1355. return result_kv
  1356. def extract_kv(self,k_pattern,from_sentence=True,from_outline=True,from_table=True):
  1357. result_kv = []
  1358. try:
  1359. re.compile(k_pattern)
  1360. except Exception as e:
  1361. log("k_pattern error: "+str(e))
  1362. traceback.print_exc()
  1363. return result_kv
  1364. result_kv = []
  1365. if from_table:
  1366. result_kv_table = self.extract_kvs_from_table([k_pattern])
  1367. for table_d in result_kv_table[0]:
  1368. table_id = table_d.get("table_id")
  1369. table_kvs = table_d.get("kv",[])
  1370. for _d in table_kvs:
  1371. _d["from_table"] = True
  1372. result_kv.extend(table_kvs)
  1373. if from_sentence:
  1374. result_kv_sentence = self.extract_kvs_from_sentence([k_pattern])
  1375. for _d in result_kv_sentence[0]:
  1376. _d["from_sentence"] = True
  1377. result_kv.extend(result_kv_sentence[0])
  1378. if from_outline:
  1379. result_kv_outline = self.extract_kvs_from_outline([k_pattern])
  1380. for _d in result_kv_outline[0]:
  1381. _d["from_outline"] = True
  1382. result_kv.extend(result_kv_outline[0])
  1383. return result_kv
  1384. # def extract_kvs_from_table(self,list_pattern):
  1385. if __name__ == '__main__':
  1386. # HTML 文本
  1387. html_content = """
  1388. <div id="pcontent"><div>
  1389. <div>
  1390. <div>
  1391. 张家港励晟塑胶制品有限公司塑料制品迁建项目竣工环境保护验收公示
  1392. </div>
  1393. <p><img rel="noreferrer" src="http://www.zjgweien.com/plugins/ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif"><a target="_blank" class="markBlue" filelink="f58f054eb12f605f7dbec00275ccb212" href="https://attachment-hub.oss-cn-hangzhou.aliyuncs.com/f58f/20241224/2024-12-24/XM10518/1734976268529.pdf?Expires=1735024508&amp;OSSAccessKeyId=LTAI5tHoEUDSy6FnZjMKsNiZ&amp;Signature=YslrkpL%2FvbjwUVzfDYd0my14W7Y%3D" original="<a target='_blank' class='markBlue' href='http://www.zjgweien.com/upload/news/yanshoubaogao.pdf' target='_blank' class='markBlue'>http://www.zjgweien.com/upload/news/yanshoubaogao.pdf</a>" rel="noreferrer" title="yanshoubaogao.pdf">yanshoubaogao.pdf</a></p>
  1394. <p><br></p>
  1395. </div>
  1396. </div>
  1397. <div style="" class="richTextFetch"><div filemd5="f58f054eb12f605f7dbec00275ccb212"><div>张家港励晟塑胶制品有限公司塑料制品迁建</div><div>项目竣工环境保护验收监测报告</div><div>建设单位:张家港励晟塑胶制品有限公司</div><div>编制单位:张家港励晟塑胶制品有限公司</div><div>2023年06月,</div><div>目录</div><div>1项目概况</div><div>2验收依据</div><div>3项目建设情况</div><div>3.1地理位置及平面布置</div><div>3.2建设内容</div><div>3.3主要原辅材料</div><div>3.4生产工艺</div><div>3.5项目变动情况</div><div>4环境保护设施</div><div>4.1污染物治理/处置设施</div><div>5建设项目环评报告表主要结论及审批意见的要求</div><div>5.1建设项目环评报告表的主要结论</div><div>6验收执行标准</div><div>6.1废气评价标准</div><div>6.2噪声评价标准</div><div>6.3固废处置标准</div><div>7验收监测内容</div><div>7.1废水</div><div>7.2废气</div><div>7.3噪声</div><div>8质量保证及质量控制</div><div>8.1监测分析方法</div><div>8.2监测仪器</div><div>8.3人员能力</div><div>8.4监测分析过程中的质量保证和质量控制</div><div>9验收监测工况及要求</div><div>10验收监测结果及分析评价</div><div>10.1废气监测结果及分析评价</div><div>10.2噪声监测结果及分析评价</div><div>10.3污染物排放总量核算</div><div>11环评及审批意见执行情况</div><div>12验收监测结论和建议</div><div>12.1验收监测结论</div><div>12.2建议</div><div>1项目概况</div><div>张家港励晟塑胶制品有限公司原厂位于凤凰镇杏市村,现搬迁至凤凰镇西参</div><div>村,主要从事塑料制品的生产制造。项目于2019年12月26日在张家港市凤凰镇人</div><div>民政府备案,备案文号:张凤申备[2019]134号。本项目于2020年7月委托江苏绿</div><div>源工程设计研究有限公司编制完成了《张家港励晟塑胶制品有限公司塑料制品迁</div><div>建项目环境影响报告表》,并于2020年10月27日通过苏州市行政审批局审批(文</div><div>号:苏环审环评[2020]10268号),该项目于2020年11月建成。</div><div>本项目环评设计建设新增吹膜机、手套机、造粒机、流延机等,年产塑料制</div><div>品20亿件。本次验收范围为张家港励晟塑胶制品有限公司塑料制品迁建项目。</div><div>本项目概况见表1-1。</div><div>表1-1项目概况表</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">建设项目</td><td colspan="1" rowspan="1">塑料制品迁建项目</td><td colspan="1" rowspan="1">塑料制品迁建项目</td><td colspan="1" rowspan="1">塑料制品迁建项目</td></tr><tr><td colspan="1" rowspan="1">建设单位</td><td colspan="1" rowspan="1">张家港励晟塑胶制品有限公司</td><td colspan="1" rowspan="1">张家港励晟塑胶制品有限公司</td><td colspan="1" rowspan="1">张家港励晟塑胶制品有限公司</td></tr><tr><td colspan="1" rowspan="1">建设项目性质</td><td colspan="1" rowspan="1">新建扩建技改迁建√</td><td colspan="1" rowspan="1">行业类别</td><td colspan="1" rowspan="1">C2929塑料零件及其他塑料制品制造</td></tr><tr><td colspan="1" rowspan="1">建设地点</td><td colspan="1" rowspan="1">张家港市凤凰镇西参村</td><td colspan="1" rowspan="1">张家港市凤凰镇西参村</td><td colspan="1" rowspan="1">张家港市凤凰镇西参村</td></tr><tr><td colspan="1" rowspan="1">环评编制单位</td><td colspan="1" rowspan="1">江苏绿源工程设计研究有限公司</td><td colspan="1" rowspan="1">环评编制时间</td><td colspan="1" rowspan="1">2020年7月</td></tr><tr><td colspan="1" rowspan="1">环评审批单位</td><td colspan="1" rowspan="1">苏州市行政审批局</td><td colspan="1" rowspan="1">环评审批时间</td><td colspan="1" rowspan="1">2020年10月27日</td></tr><tr><td colspan="1" rowspan="1">开工时间</td><td colspan="1" rowspan="1">2020年11月</td><td colspan="1" rowspan="1">调试时间</td><td colspan="1" rowspan="1">2020年11月</td></tr><tr><td colspan="1" rowspan="1">排污许可登记编号</td><td colspan="1" rowspan="1">91320582689615143D001W</td><td colspan="1" rowspan="1">有效期</td><td colspan="1" rowspan="1">2023年4月28日至2028年4月27日</td></tr><tr><td colspan="1" rowspan="1">环评设计能力</td><td colspan="1" rowspan="1">年产塑料制品20亿件</td><td colspan="1" rowspan="1">年产塑料制品20亿件</td><td colspan="1" rowspan="1">年产塑料制品20亿件</td></tr><tr><td colspan="1" rowspan="1">实际建设能力</td><td colspan="1" rowspan="1">年产塑料制品20亿件</td><td colspan="1" rowspan="1">年产塑料制品20亿件</td><td colspan="1" rowspan="1">年产塑料制品20亿件</td></tr><tr><td colspan="1" rowspan="1">现场验收监测时间</td><td colspan="1" rowspan="1">2022年10月24日至2022年10月25日</td><td colspan="1" rowspan="1">2022年10月24日至2022年10月25日</td><td colspan="1" rowspan="1">2022年10月24日至2022年10月25日</td></tr></tbody></table><div>张家港励晟塑胶制品有限公司,第1页共20页</div><div>2验收依据</div><div>2.1建设项目环境保护相关法律、法规和规章制度</div><div>(1)《中华人民共和国环境保护法》(2015年1月1日起施行)</div><div>(2)《中华人民共和国水污染防治法》(2018年1月1日起施行);</div><div>(3)《中华人民共和国大气污染防治法》(2018年10月26日施行);</div><div>(4)《中华人民共和国环境噪声污染防治法》(2022年6月5日起施行);</div><div>(5)《中华人民共和国固体废物污染环境防治法》(2020年9日1日起施行);</div><div>(6)《建设项目环境保护管理条例》(中华人民共和国国务院令第682号,2017年</div><div>7月16日)。</div><div>2.2建设项目竣工环境保护验收技术规范</div><div>(1)《建设项目竣工环境保护验收管理办法》(原国家环境保护总局令第13</div><div>号,2001年12月27日)</div><div>(2)《关于规范建设单位自主开展建设项目竣工环境保护验收的通知(征求</div><div>意见稿)》意见的通知(环办环评函[2017]1235号,2017年8月3日);</div><div>(3)《建设项目竣工环境保护验收技术指南污染影响类》意见的通知(生</div><div>态环境部2018年第9号公告,2018年5月15日);</div><div>(4)关于印发《污染影响类建设项目重大变动清单(试行)》的通知(环办</div><div>环评函[2020]688号);</div><div>(5)《省生态环境厅关于加强涉变动项目环评与排污许可管理衔接的通知》</div><div>(苏环办[2021]122号);</div><div>(6)《排污单位自行监测技术指南总则》(HJ819-2017)。</div><div>2.3建设项目环境影响报告书(表)及其审批部门审批决定:</div><div>(1)《张家港励晟塑胶制品有限公司塑料制品迁建项目环境影响报告表》</div><div>(江苏绿源工程设计研究有限公司,2020年7月);</div><div>(2)苏州市行政审批局关于对张家港励晟塑胶制品有限公司塑料制品迁建项</div><div>目环境影响报告表的审批意见(2020年10月27日)。</div><div>2.4其他相关文件。</div><div>(1)《排污许可管理条例》(中华人民共和国国务院令第736号,2021年1月</div><div>24日);</div><div>张家港励晟塑胶制品有限公司,第2页共20页</div><div>(2)《国家危险废物名录(2021年版)》(部令第15号,2020年11月25日);</div><div>(3)《一般工业固体废物贮存和填埋污染控制标准》(GB18599-2020)。</div><div>(4)《危险废物贮存污染控制标准》(GB18597-2023)。</div><div>3项目建设情况</div><div>3.1地理位置及平面布置</div><div>本项目位于张家港市凤凰镇西参村。项目厂界西侧为天源塑业,南侧为张家</div><div>港东旭针织服饰有限公司,北侧为西塘公路,隔路为张家港市佳暖纺织有限公司。</div><div>本项目地理位置、周边环境概况、平面布置及监测点位见下图(噪声测点点</div><div>位见附件检测报告)。,</div><div>张家港励晟塑胶制品有限公司,第3页共20页</div><div>张家港行政图</div><div>州</div><div>双山备山</div><div>度</div><div>本项目位置常代</div><div>业地国</div><div>无</div><div>图3.1-1地理位置图</div><div>北</div><div>西社区居民约40户</div><div>阳百社区</div><div>计</div><div>以生产车间为边界向外</div><div>设置50m卫生防护距离</div><div>港东旭针</div><div>西公路</div><div>家堂居民10户</div><div>以造粒车间为边界向外图例</div><div>设置100m卫生防护距离</div><div>本项目位置</div><div>L=300米</div><div>比例尺:</div><div>0259075100me-5</div><div>污水管网</div><div>图3.1-2周边环境图</div><div>张家港励晟塑胶制品有限公司,第4页共20页</div><div>图3.1-3平面布置及监测点位图</div><div>张家港励晟塑胶制品有限公司,第5页共20页</div><div>3.2建设内容</div><div>(1)原有项目回顾</div><div>与本项目有关的企业原有已批已建的项目情况如下:</div><div>表3.2-1与本项目有关的原有项目情况</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">建设地点</td><td colspan="1" rowspan="1">项目名称</td><td colspan="1" rowspan="1">建设内容</td><td colspan="1" rowspan="1">环评批复及时间</td><td colspan="1" rowspan="1">验收批复及时间</td><td colspan="1" rowspan="1">备注</td></tr><tr><td colspan="1" rowspan="1">杏市村</td><td colspan="1" rowspan="1">“塑料制品、橡胶制品项目”环境影响登记表</td><td colspan="1" rowspan="1">年产塑料制品1000吨</td><td colspan="1" rowspan="1">2009.04.10通过张家港市环境保护局审批意见</td><td colspan="1" rowspan="1">-</td><td colspan="1" rowspan="1">已搬迁</td></tr><tr><td colspan="1" rowspan="1">杏市村</td><td colspan="1" rowspan="1">“年产塑料制品1000吨项目”自查评估报告</td><td colspan="1" rowspan="1">年产塑料制品1000吨</td><td colspan="1" rowspan="1">2016.11.08通过张家港市环境保护局审批意见</td><td colspan="1" rowspan="1">-</td><td colspan="1" rowspan="1">已搬迁</td></tr></tbody></table><div>(2)本项目情况</div><div>本项目建设情况见表3.2-2,产品方案见表3.2-3,主要生产设备见表3.2-4,</div><div>公辅工程见表3.2-5。</div><div>表3.2-2本项目建设情况</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">类型</td><td colspan="1" rowspan="1">环评/审批项目内容</td><td colspan="1" rowspan="1">实际建设情况</td></tr><tr><td colspan="1" rowspan="1">地理位置</td><td colspan="1" rowspan="1">本项目位于张家港市凤凰镇西参村。</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">总投资</td><td colspan="1" rowspan="1">总投资500万元人民币,其中环保投资50万元。</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">定员与生产制度</td><td colspan="1" rowspan="1">本项目不新增员工,全厂职工40人,年工作300天,实行两班制,每班10h,全年工作6000小时。</td><td colspan="1" rowspan="1">与环评不一致。全厂职工40人,年工作300天,实行两班制,每班8h,全年工作4800h。</td></tr><tr><td colspan="1" rowspan="1">占地面积</td><td colspan="1" rowspan="1">占地面积2500平方米,建筑面积4000平方米。</td><td colspan="1" rowspan="1">与环评一致</td></tr></tbody></table><div>表3.2-3本项目产品方案一览表</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">名称</td><td colspan="1" rowspan="1">本项目产能(亿件)</td><td colspan="1" rowspan="1">本项目产能(亿件)</td><td colspan="1" rowspan="1">储存方式及地点</td><td colspan="1" rowspan="1">实际建设</td></tr><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">名称</td><td colspan="1" rowspan="1">环评设计</td><td colspan="1" rowspan="1">实际建设</td><td colspan="1" rowspan="1">储存方式及地点</td><td colspan="1" rowspan="1">实际建设</td></tr><tr><td colspan="1" rowspan="1">1</td><td colspan="1" rowspan="1">塑料制品</td><td colspan="1" rowspan="1">20</td><td colspan="1" rowspan="1">20</td><td colspan="1" rowspan="1">仓库</td><td colspan="1" rowspan="1">与环评一致</td></tr></tbody></table><div>表3.2-4本项目主要生产设备及数量</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">设备名称</td><td colspan="1" rowspan="1">设备规格(型号)</td><td colspan="1" rowspan="1">设备数量(台)</td><td colspan="1" rowspan="1">设备数量(台)</td><td colspan="1" rowspan="1">备注</td></tr><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">设备名称</td><td colspan="1" rowspan="1">设备规格(型号)</td><td colspan="1" rowspan="1">环评设计</td><td colspan="1" rowspan="1">实际建设</td><td colspan="1" rowspan="1">备注</td></tr><tr><td colspan="1" rowspan="1">1</td><td colspan="1" rowspan="1">混料机</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">6</td><td colspan="1" rowspan="1">10</td><td colspan="1" rowspan="1">新增4台</td></tr><tr><td colspan="1" rowspan="1">2</td><td colspan="1" rowspan="1">吹膜机</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">18</td><td colspan="1" rowspan="1">18</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">3</td><td colspan="1" rowspan="1">手套机</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">32</td><td colspan="1" rowspan="1">30</td><td colspan="1" rowspan="1">减少2台</td></tr><tr><td colspan="1" rowspan="1">4</td><td colspan="1" rowspan="1">造粒机</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">4</td><td colspan="1" rowspan="1">4</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">5</td><td colspan="1" rowspan="1">冲床</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">1</td><td colspan="1" rowspan="1">3</td><td colspan="1" rowspan="1">新增2台</td></tr><tr><td colspan="1" rowspan="1">6</td><td colspan="1" rowspan="1">流延机</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">3</td><td colspan="1" rowspan="1">2</td><td colspan="1" rowspan="1">减少1台</td></tr><tr><td colspan="1" rowspan="1">7</td><td colspan="1" rowspan="1">空压机</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">3</td><td colspan="1" rowspan="1">3</td><td colspan="1" rowspan="1">与环评一致</td></tr></tbody></table><div>表3.2-5本项目公辅工程</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">类别</td><td colspan="1" rowspan="1">建设名称</td><td colspan="1" rowspan="1">建设名称</td><td colspan="1" rowspan="1">设计能力</td><td colspan="1" rowspan="1">环评设计</td><td colspan="1" rowspan="1">实际建设</td></tr><tr><td colspan="1" rowspan="1">主体工程</td><td colspan="1" rowspan="1">生产车间</td><td colspan="1" rowspan="1">生产车间</td><td colspan="1" rowspan="1">2500m2</td><td colspan="1" rowspan="1">从事生产活动</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">主体工程</td><td colspan="1" rowspan="1">办公区</td><td colspan="1" rowspan="1">办公区</td><td colspan="1" rowspan="1">200m2</td><td colspan="1" rowspan="1">位于生产车间内,从事办公活动</td><td colspan="1" rowspan="1">位于车间二楼,面积不变</td></tr><tr><td colspan="1" rowspan="1">储运工程</td><td colspan="1" rowspan="1">仓库</td><td colspan="1" rowspan="1">仓库</td><td colspan="1" rowspan="1">100m2</td><td colspan="1" rowspan="1">位于生产车间内,用于成品堆放</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">公用工程</td><td colspan="1" rowspan="1">供水</td><td colspan="1" rowspan="1">生活用水</td><td colspan="1" rowspan="1">720t/a</td><td colspan="1" rowspan="1">经化粪池预处理后接管至张家港市给排水有限公司塘桥片区污水处理厂处理</td><td colspan="1" rowspan="1">由于本项目厂区生活污水管网尚未接通,项目生活污水只能汇入村里集中化粪池,由村里负责委托污水厂定期拖运</td></tr><tr><td colspan="1" rowspan="1">公用工程</td><td colspan="1" rowspan="1">供水</td><td colspan="1" rowspan="1">冷却循环水</td><td colspan="1" rowspan="1">50t/a</td><td colspan="1" rowspan="1">循环回用,不外排</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">公用工程</td><td colspan="1" rowspan="1">供电</td><td colspan="1" rowspan="1">供电</td><td colspan="1" rowspan="1">14万kwh/a</td><td colspan="1" rowspan="1">当地电网</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">环保工程</td><td colspan="1" rowspan="1">废气处理</td><td colspan="1" rowspan="1">废气处理</td><td colspan="1" rowspan="1">干式过滤+活性炭吸附</td><td colspan="1" rowspan="1">1套</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">环保工程</td><td colspan="1" rowspan="1">生活废水</td><td colspan="1" rowspan="1">生活废水</td><td colspan="1" rowspan="1">化粪池</td><td colspan="1" rowspan="1">经化粪池预处理后接管至张家港市给排水有限公司塘桥片区污水处理厂处理</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">环保工程</td><td colspan="1" rowspan="1">噪声处理</td><td colspan="1" rowspan="1">噪声处理</td><td colspan="1" rowspan="1">隔声降噪措施</td><td colspan="1" rowspan="1">隔声量≥25dB(A)</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">环保工程</td><td colspan="1" rowspan="1">固废处理</td><td colspan="1" rowspan="1">固废处理</td><td colspan="1" rowspan="1">一般固废堆场</td><td colspan="1" rowspan="1">10m2</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">环保工程</td><td colspan="1" rowspan="1">固废处理</td><td colspan="1" rowspan="1">固废处理</td><td colspan="1" rowspan="1">危废仓库</td><td colspan="1" rowspan="1">10m2</td><td colspan="1" rowspan="1">与环评一致</td></tr></tbody></table><div>3.3主要原辅材料</div><div>表3.2-6本项目原辅材料用量表</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">名称</td><td colspan="1" rowspan="1">使用量(t/a)</td><td colspan="1" rowspan="1">使用量(t/a)</td><td colspan="1" rowspan="1">储存方式</td><td colspan="1" rowspan="1">包装规格</td><td colspan="1" rowspan="1">实际建设</td></tr><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">名称</td><td colspan="1" rowspan="1">环评设计</td><td colspan="1" rowspan="1">实际建设</td><td colspan="1" rowspan="1">储存方式</td><td colspan="1" rowspan="1">包装规格</td><td colspan="1" rowspan="1">实际建设</td></tr><tr><td colspan="1" rowspan="1">1</td><td colspan="1" rowspan="1">PE塑料粒子</td><td colspan="1" rowspan="1">1000</td><td colspan="1" rowspan="1">1000</td><td colspan="1" rowspan="1">仓库存储</td><td colspan="1" rowspan="1">袋装</td><td colspan="1" rowspan="1">与环评一致</td></tr><tr><td colspan="1" rowspan="1">2</td><td colspan="1" rowspan="1">色母粒</td><td colspan="1" rowspan="1">10</td><td colspan="1" rowspan="1">10</td><td colspan="1" rowspan="1">仓库存储</td><td colspan="1" rowspan="1">袋装</td><td colspan="1" rowspan="1">与环评一致</td></tr></tbody></table><div>张家港励晟塑胶制品有限公司,第7页共20页</div><div>3.4生产工艺</div><div>3.4.1生产工艺流程图</div><div>图3.4-1本项目工艺流程图</div><div>工艺流程简述:</div><div>混料:根据生产需要PE粒子和色母粒按比例投入料斗混合,此工序产生集线</div><div>器噪声N1;</div><div>吹膜:塑料粒子加热融化,工艺的加热温度为130℃~160℃,将塑料挤成薄管,</div><div>然后趁热将塑料吹胀,此工序产生机器噪声N2以及有机废气G1;</div><div>流延:通过三层共挤流延成薄膜,流延机加热温度200℃,此工序产生一定的</div><div>机器噪声N3以及有机废气G2;</div><div>剪切、冲压:根据产品需求对薄膜进行剪切,其中用于制作手套的薄膜需进</div><div>行冲压处理,此工序产生机器噪声N4;</div><div>封口、包装:部分薄膜经手套制作(电熔、烫口等)后封口包装入库,其他</div><div>产品直接封口包装入库,此工序产生机器噪声N5以及少量得有机废气G3;</div><div>造粒:剪切、冲压产生的边角料重新进行造粒后回用。造粒使用边角料,造</div><div>张家港励晟塑胶制品有限公司,第8页共20页</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">G3下风向</td><td colspan="1" rowspan="1">第一次</td><td colspan="1" rowspan="1">0.39</td><td colspan="1" rowspan="1">0.40</td><td colspan="1" rowspan="1">0.159</td><td colspan="1" rowspan="1">0.141</td></tr><tr><td colspan="1" rowspan="1">G3下风向</td><td colspan="1" rowspan="1">第二次</td><td colspan="1" rowspan="1">0.41</td><td colspan="1" rowspan="1">0.36</td><td colspan="1" rowspan="1">0.124</td><td colspan="1" rowspan="1">0.176</td></tr><tr><td colspan="1" rowspan="1">G3下风向</td><td colspan="1" rowspan="1">第三次</td><td colspan="1" rowspan="1">0.40</td><td colspan="1" rowspan="1">0.38</td><td colspan="1" rowspan="1">0.213</td><td colspan="1" rowspan="1">0.159</td></tr><tr><td colspan="1" rowspan="1">G4下风向</td><td colspan="1" rowspan="1">第一次</td><td colspan="1" rowspan="1">0.40</td><td colspan="1" rowspan="1">0.36</td><td colspan="1" rowspan="1">0.141</td><td colspan="1" rowspan="1">0.106</td></tr><tr><td colspan="1" rowspan="1">G4下风向</td><td colspan="1" rowspan="1">第二次</td><td colspan="1" rowspan="1">0.40</td><td colspan="1" rowspan="1">0.34</td><td colspan="1" rowspan="1">0.195</td><td colspan="1" rowspan="1">0.123</td></tr><tr><td colspan="1" rowspan="1">G4下风向</td><td colspan="1" rowspan="1">第三次</td><td colspan="1" rowspan="1">0.40</td><td colspan="1" rowspan="1">0.47</td><td colspan="1" rowspan="1">0.160</td><td colspan="1" rowspan="1">0.177</td></tr><tr><td colspan="1" rowspan="1">最大值</td><td colspan="1" rowspan="1">最大值</td><td colspan="1" rowspan="1">0.41</td><td colspan="1" rowspan="1">0.47</td><td colspan="1" rowspan="1">0.213</td><td colspan="1" rowspan="1">0.212</td></tr><tr><td colspan="1" rowspan="1">标准值</td><td colspan="1" rowspan="1">标准值</td><td colspan="1" rowspan="1">4.0</td><td colspan="1" rowspan="1">4.0</td><td colspan="1" rowspan="1">1.0</td><td colspan="1" rowspan="1">1.0</td></tr><tr><td colspan="1" rowspan="1">达标情况</td><td colspan="1" rowspan="1">达标情况</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td></tr></tbody></table><div>表10.1-3厂区内无组织排放废气监测结果统计表单位:mg/m³</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">监测点位</td><td colspan="1" rowspan="1">频次</td><td colspan="1" rowspan="1">非甲烷总烃</td><td colspan="1" rowspan="1">非甲烷总烃</td></tr><tr><td colspan="1" rowspan="1">监测点位</td><td colspan="1" rowspan="1">频次</td><td colspan="1" rowspan="1">10月24日</td><td colspan="1" rowspan="1">10月25日</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">第一次</td><td colspan="1" rowspan="1">0.43</td><td colspan="1" rowspan="1">0.48</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">第二次</td><td colspan="1" rowspan="1">0.43</td><td colspan="1" rowspan="1">0.40</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">第三次</td><td colspan="1" rowspan="1">0.40</td><td colspan="1" rowspan="1">0.39</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">均值</td><td colspan="1" rowspan="1">0.42</td><td colspan="1" rowspan="1">0.42</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">最大值</td><td colspan="1" rowspan="1">0.43</td><td colspan="1" rowspan="1">0.48</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">标准值</td><td colspan="1" rowspan="1">6</td><td colspan="1" rowspan="1">6</td></tr><tr><td colspan="1" rowspan="1">G5厂区车间门外1m处</td><td colspan="1" rowspan="1">达标情况</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td></tr></tbody></table><div>10.1.3结果评价</div><div>监测结果表明:验收监测期间,本项目废气排放浓度最大值排放浓度均达到</div><div>《合成树脂工业污染物排放标准》(GB31572-2015)、《大气污染物综合排放标</div><div>准》(GB16297-1996)以及江苏省《大气污染物综合排放标准》(DB32/4041-</div><div>2021)限值要求。</div><div>10.2噪声监测结果及分析评价</div><div>10.2.1本项目噪声监测结果见表10.2-1。监测点位见附图。</div><div>表10.2-1厂界环境噪声监测结果汇总表LeqdB(A)</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">测点编号</td><td colspan="1" rowspan="1">测点名称</td><td colspan="1" rowspan="1">监测时间</td><td colspan="1" rowspan="1">监测时间</td><td colspan="1" rowspan="1">监测时间</td><td colspan="1" rowspan="1">监测时间</td></tr><tr><td colspan="1" rowspan="1">测点编号</td><td colspan="1" rowspan="1">测点名称</td><td colspan="1" rowspan="1">2022.10.24</td><td colspan="1" rowspan="1">2022.10.24</td><td colspan="1" rowspan="1">2022.10.25</td><td colspan="1" rowspan="1">2022.10.25</td></tr><tr><td colspan="1" rowspan="1">测点编号</td><td colspan="1" rowspan="1">测点名称</td><td colspan="1" rowspan="1">昼间</td><td colspan="1" rowspan="1">夜间</td><td colspan="1" rowspan="1">昼间</td><td colspan="1" rowspan="1">夜间</td></tr><tr><td colspan="1" rowspan="1">N1</td><td colspan="1" rowspan="1">项目东侧厂界外1米</td><td colspan="1" rowspan="1">53.7</td><td colspan="1" rowspan="1">48.4</td><td colspan="1" rowspan="1">54.0</td><td colspan="1" rowspan="1">48.5</td></tr><tr><td colspan="1" rowspan="1">N2</td><td colspan="1" rowspan="1">项目南侧厂界外1米</td><td colspan="1" rowspan="1">54.5</td><td colspan="1" rowspan="1">49.0</td><td colspan="1" rowspan="1">54.8</td><td colspan="1" rowspan="1">49.3</td></tr><tr><td colspan="1" rowspan="1">N3</td><td colspan="1" rowspan="1">项目西侧厂界外1米</td><td colspan="1" rowspan="1">52.8</td><td colspan="1" rowspan="1">47.3</td><td colspan="1" rowspan="1">52.7</td><td colspan="1" rowspan="1">47.3</td></tr><tr><td colspan="1" rowspan="1">N4</td><td colspan="1" rowspan="1">项目北侧厂界外1米</td><td colspan="1" rowspan="1">53.3</td><td colspan="1" rowspan="1">47.8</td><td colspan="1" rowspan="1">53.5</td><td colspan="1" rowspan="1">48.0</td></tr><tr><td colspan="1" rowspan="1">标准限值</td><td colspan="1" rowspan="1">标准限值</td><td colspan="1" rowspan="1">60</td><td colspan="1" rowspan="1">50</td><td colspan="1" rowspan="1">60</td><td colspan="1" rowspan="1">50</td></tr><tr><td colspan="1" rowspan="1">达标情况</td><td colspan="1" rowspan="1">达标情况</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td><td colspan="1" rowspan="1">达标</td></tr></tbody></table><div>10.2.2结果评价</div><div>监测结果表明:验收监测期间,本项目厂界环境噪声测点昼夜间等效声级值</div><div>均满足《工业企业厂界环境噪声排放标准》(GB12348-2008)2类标准限值要求。</div><div>10.3污染物排放总量核算</div><div>10.3.1废水污染物排放总量</div><div>由于本项目用水简单,用水仅为员工生活用水,无工业废水外排,因为本项</div><div>目不对废水情况进行检测分析。具体见表10.3-1。</div><div>表10.3-1废水污染物排放总量与控制指标对照</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">污染物排放口</td><td colspan="1" rowspan="1">污染物排放口</td><td colspan="1" rowspan="1">废水量</td><td colspan="1" rowspan="1">化学需氧量</td><td colspan="1" rowspan="1">悬浮物</td><td colspan="1" rowspan="1">氨氮</td><td colspan="1" rowspan="1">总磷</td></tr><tr><td colspan="1" rowspan="1">生活污水排放口S1</td><td colspan="1" rowspan="1">排放浓度(mg/L)</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td></tr><tr><td colspan="1" rowspan="1">生活污水排放口S1</td><td colspan="1" rowspan="1">排放量(t/a)</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td><td colspan="1" rowspan="1">/</td></tr><tr><td colspan="1" rowspan="1">环评批复接管总量(t/a)</td><td colspan="1" rowspan="1">环评批复接管总量(t/a)</td><td colspan="1" rowspan="1">576</td><td colspan="1" rowspan="1">0.23</td><td colspan="1" rowspan="1">0.115</td><td colspan="1" rowspan="1">0.02</td><td colspan="1" rowspan="1">0.002</td></tr><tr><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td><td colspan="1" rowspan="1">备注:由于本项目用水简单,全厂员工40人,用水仅为员工生活用水,无工业废水外排,因此本项目不对废水情况进行检测分析。</td></tr></tbody></table><div>10.3.2废气污染物排放总量</div><div>本项目废气主要为吹膜、流延、封口和造粒工序产生的有机废气以及粉尘,</div><div>项目废气经1套干式过滤(过滤棉)+二级活性炭吸附装置处理后通过1根15m高排</div><div>气筒排放。根据本次验收监测结果计算废气污染物排放总量,本项目废气总量满</div><div>足环评批复要求。具体见表10.3-2。</div><div>表10.3-2废气污染物排放总量与控制指标对照</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">污染物排放口</td><td colspan="1" rowspan="1">污染物排放口</td><td colspan="1" rowspan="1">非甲烷总烃</td><td colspan="1" rowspan="1">颗粒物</td></tr><tr><td colspan="1" rowspan="1">有组织废气排放口P1</td><td colspan="1" rowspan="1">排放浓度(mg/m³)</td><td colspan="1" rowspan="1">0.38</td><td colspan="1" rowspan="1">1.5</td></tr><tr><td colspan="1" rowspan="1">有组织废气排放口P1</td><td colspan="1" rowspan="1">排放速率(kg/h)</td><td colspan="1" rowspan="1">0.0047</td><td colspan="1" rowspan="1">0.013</td></tr><tr><td colspan="1" rowspan="1">有组织废气排放口P1</td><td colspan="1" rowspan="1">排放量(t/a)</td><td colspan="1" rowspan="1">0.0113</td><td colspan="1" rowspan="1">0.0039(造粒年工作时间约300h)</td></tr><tr><td colspan="1" rowspan="1">环评批复总量(t/a)</td><td colspan="1" rowspan="1">环评批复总量(t/a)</td><td colspan="1" rowspan="1">0.0378</td><td colspan="1" rowspan="1">0.0045</td></tr><tr><td colspan="1" rowspan="1">备注:/</td><td colspan="1" rowspan="1">备注:/</td><td colspan="1" rowspan="1">备注:/</td><td colspan="1" rowspan="1">备注:/</td></tr></tbody></table><div>11环评及审批意见执行情况</div><div>张家港励晟塑胶制品有限公司塑料制品迁建项目环境影响报告表及审批意见</div><div>张家港励晟塑胶制品有限公司,第17页共20页</div><div>执行情况见表11.1-1。</div><div>表11.1-1环评报告表及其审批意见执行情况一览表</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">序号</td><td colspan="1" rowspan="1">环评审批意见</td><td colspan="1" rowspan="1">执行情况</td></tr><tr><td colspan="1" rowspan="1">1</td><td colspan="1" rowspan="1">项目位于凤凰镇西参村,搬迁项目投资500万元,新增相应生产设备进行生产,项目搬迁投产后,全厂年产PE手套等各类塑料制品20亿件。</td><td colspan="1" rowspan="1">本项目建设地址、投资额、成品情况与环评相一致。设备较环评新增4台混料机、2台手套机、2台冲床,减少1台流延机。</td></tr><tr><td colspan="1" rowspan="1">2</td><td colspan="1" rowspan="1">本项目生活污水接管至张家港市给排水公司塘桥片区污水处理厂集中处理,达标排放。</td><td colspan="1" rowspan="1">本项目厂区生活污水外管网尚未接通,项目生活污水只能汇入村里集中化粪池,由村里负责委托污水厂定期拖运。</td></tr><tr><td colspan="1" rowspan="1">3</td><td colspan="1" rowspan="1">本项目吹膜、流延、封口、造粒产生的有机废气和颗粒物经集气罩收集后经1套干式过滤(过滤棉)+活性炭吸附装置处理后通过一根15米高排气筒排放,以上废气执行相应</td><td colspan="1" rowspan="1">项目有机废气和颗粒物经集气罩收集后经1套干式过滤(过滤棉)+二级活性炭吸附装置处理后通过一根15米高排气筒达标排放。</td></tr><tr><td colspan="1" rowspan="1">4</td><td colspan="1" rowspan="1">制定有效措施控制项目运营期的噪声,厂界噪声排放执行《工业企业厂界环境噪声排放标准》(GB12348-2008)2类。</td><td colspan="1" rowspan="1">本项目合理布局厂区,采用低噪声设备,高噪音设备采取了相应的减振、隔声等降噪措施。根据监测结果表明:验收监测期间,该公司厂界环境噪声测点昼、夜间等效声级值均满足《工业企业厂界环境噪声排放标准》(GB12348-2008)2类标准限值要求。</td></tr><tr><td colspan="1" rowspan="1">5</td><td colspan="1" rowspan="1">制定和落实固体废物的厂内收集和贮存、综合利用、安全处置的实施方案,实现“零排放”。</td><td colspan="1" rowspan="1">本项目在厂区内设置一个危废仓库,一般固废收集后外卖,危险固废委托有资质单位处理,实现“零排放”。</td></tr><tr><td colspan="1" rowspan="1">6</td><td colspan="1" rowspan="1">该项目实施后,建设单位应落实环评文件提出的以生产车间为边界向外设置50米卫生防护距离,以造粒车间为边界向外设置100米卫生防护距离的要求。</td><td colspan="1" rowspan="1">本项目卫生防护距离范围内无居民等环境敏感目标。</td></tr><tr><td colspan="1" rowspan="1">7</td><td colspan="1" rowspan="1">严格落实环境风险的防范措施,避免风险事故。建设单位应强化环境风险意识,从技术、工艺、管理等方面加强落实防范措施。</td><td colspan="1" rowspan="1">公司在后续经营过程中会不断强化环境风险意识,从技术、工艺、管理等方面加强落实防范措施。</td></tr><tr><td colspan="1" rowspan="1">8</td><td colspan="1" rowspan="1">该项目在设计、施工建设和生产中总平面布局以及主要工艺设备、储运设施、公辅工程、污染防治设施安装、使用中涉及安全生产的应遵守设计使用规范和相关主管部门要求;建设单位应对环境治理设施开展安全风险辨识管控,要健全内部污染防治设施稳定运行和管理责任制度,严格依据标准规范建设环境治理设施,确保环境治理设施安全、稳定、有效运行。</td><td colspan="1" rowspan="1">公司在建设过程中严格按照设计使用规范和相关主管部门要求开展。建立内部污染防治设施稳定运行和管理责任制度,严格依据标准规范建设环境治理设施。</td></tr><tr><td colspan="1" rowspan="1">9</td><td colspan="1" rowspan="1">按《江苏省排污口设置及规范化整治管理办法》(苏环控(1997)122号)的要求完善各类排污口和标志设置。</td><td colspan="1" rowspan="1">本项目排放口均按照要求完善标志设置。</td></tr><tr><td colspan="1" rowspan="1">10</td><td colspan="1" rowspan="1">严格落实《报告表》提出的监测计划。</td><td colspan="1" rowspan="1">根据《固定污染源排污许可分类管理名录(2019年版)》本项目属于二十四、橡胶和塑料制品业29-62塑料制品业-其他,实行登记管理,建设单位已完成排污登记并生成排污编号。</td></tr><tr><td colspan="1" rowspan="1">11</td><td colspan="1" rowspan="1">控制设备调试期间的噪声污染,应尽量采用低噪声的器械,避免夜间进行高噪声污染,减轻对厂界周围声环境的影响。</td><td colspan="1" rowspan="1">本项目均采用低噪声设备,夜间生产噪声污染较小,对厂界周围声环境影响不大。</td></tr><tr><td colspan="1" rowspan="1">12</td><td colspan="1" rowspan="1">你公司应当按照《排污许可管理条例》规定,及时申请排污许可证;未取得排污许可证的,不得排放污染物。按照《建设项目竣工环境保护验收暂行办法》办理环保设施竣工验收手续。需要配套建设的环境保护设施未建成,未经验收或者经验收不合格,建设项目已投入生产或者使用的,生态环境部门将依法进行查处。</td><td colspan="1" rowspan="1">公司已取得排污许可证,配套建设的环境保护设施经验收合格后投入生产。</td></tr><tr><td colspan="1" rowspan="1">13</td><td colspan="1" rowspan="1">建设单位是该建设项目环境信息公开的主体,须自收到我局批复后及时将项目报告表的最终版本予以公开。同时应按照《建设项目环境影响评价信息公开机制方案》(环发[2015]162号)做好建设项目开工前、施工期和建成后的信息公开工作。</td><td colspan="1" rowspan="1">建设严格落实环评批复内容,公开项目建设情况。</td></tr><tr><td colspan="1" rowspan="1">14</td><td colspan="1" rowspan="1">如该项目所涉及污染物排放标准发生变化,应执行最新的排放标准。</td><td colspan="1" rowspan="1">验收监测期间本项目执行标准未发生变化,后续将严格按照标准限值要求执行。若标准发生变化,将严格按照最新标准执行。</td></tr><tr><td colspan="1" rowspan="1">15</td><td colspan="1" rowspan="1">该项目在建设过程中若项目的性质、规模、地点,采用的生产工艺或者防治污染、防止生态破坏的措施、设施发生重大变动的,应当重新报批项目的环境影响评价文件。自批准之日起,如超过5年方决定工程开工建设的,环境影响评价文件须报重新审核。</td><td colspan="1" rowspan="1">本项目于2020年10月27日取得苏州市行政审批局批复意见,并于2022年11月设备进厂调试,建设内容基本与环评相一致,无重大变动。</td></tr></tbody></table><div>12验收监测结论和建议</div><div>12.1验收监测结论</div><div>验收监测期间(2022年10月24日-25日)本项目生产正常,各项环保治理设施</div><div>均运转正常,满足验收监测要求。</div><div>验收监测期间,本项目废气排放均满足《合成树脂工业污染物排放标准》</div><div>(GB31572-2015)标准限值。</div><div>验收监测期间,本项目厂界环境噪声测点昼、夜间等效声级值均满足《工业</div><div>企业厂界环境噪声排放标准》(GB12348-2008)2类标准限值要求。</div><div>验收监测期间,本项目危险固废均得到有效处置,实现零排放。</div><div>12.2建议</div><div>1、进一步加强危废仓库的管理,做好台账记录;</div><div>2、做好高噪声设备的降噪措施,尽量减少对周边环境的影响;</div><div>3、加强管理,进一步提高公司员工的环境意识,倡导清洁生产,并加强各种</div><div>原料的储存、运送管理,制定严格的规章制度。</div><div>附件:</div><div>1、张家港励晟塑胶制品有限公司塑料制品迁建项目环境影响报告表的审批意见;</div><div>2、张家港励晟塑胶制品有限公司排水许可证;</div><div>3、张家港励晟塑胶制品有限公司生活垃圾处理协议;</div><div>4、张家港励晟塑胶制品有限公司塑料制品迁建项目验收委托检测报告;</div><div>5、苏州捷盈环境检测有限公司检验检测机构资质认定证书。</div><div>张家港励晟塑胶制品有限公司,第20页共20页</div><div>张家港励晟塑胶制品有限公司塑料制品迁建项目竣工环境保护验收</div><div>验收组人员名单</div><div>38电市风国续西叁社时间:2023.7.2</div><div>地点:</div><table border="1"><tbody><tr><td colspan="1" rowspan="1">姓名</td><td colspan="1" rowspan="1">单位名称</td><td colspan="1" rowspan="1">职务/职称</td><td colspan="1" rowspan="1">联系电话</td><td colspan="1" rowspan="1">签名</td><td colspan="1" rowspan="1">签名</td></tr><tr><td colspan="1" rowspan="1">陕到国</td><td colspan="1" rowspan="1">张家港的晟至级制项</td><td colspan="1" rowspan="1">关经理</td><td colspan="1" rowspan="1">13606226413</td><td colspan="1" rowspan="1">22</td><td colspan="1" rowspan="1">22</td></tr><tr><td colspan="1" rowspan="1">上怡</td><td colspan="1" rowspan="1">苏洲提盈环境检有限司</td><td colspan="1" rowspan="1">技术员</td><td colspan="1" rowspan="1">5950947777</td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1">科</td><td colspan="1" rowspan="1">北卷市约里261名了前2司</td><td colspan="1" rowspan="1">投求台</td><td colspan="1" rowspan="1">13061661423</td><td colspan="1" rowspan="1">WIY</td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1">史提</td><td colspan="1" rowspan="1">13805561786</td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr><tr><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td><td colspan="1" rowspan="1"></td></tr></tbody></table><div>张家港励晟塑胶制品有限公司塑料制品迁建项目竣工环境保护验收</div><div>意见</div><div>根据《建设项目环境保护管理条例》规定,2023年7月27日,张家港</div><div>励晟塑胶制品有限公司组织验收报告编制单位(张家港市维恩环境咨询</div><div>有限公司)、验收监测单位(苏州捷盈环境检测有限公司)的代表以及专</div><div>家组成验收工作组,对公司“塑料制品迁建项目”进行竣工环境保护验</div><div>收。验收工作组听取了建设单位对项目环境保护执行情况的汇报和验收</div><div>监测单位对项目竣工环境保护验收监测情况的汇报,踏勘了建设项目现</div><div>场,审阅并核实了有关资料,经认真讨论,形成竣工环保验收意见如下:</div><div>一、工程建设基本情况</div><div>(一)建设地点、规模、主要建设内容</div><div>建设地点:位于张家港市凤凰镇西参村。</div><div>建设规模及主要建设内容:本项目原厂位于凤凰镇杏市村,现搬迁</div><div>至凤凰镇西参村,项目投资500万元,将原厂的生产设备搬入新厂房内,</div><div>从事塑料制品的生产制造。搬迁后年产量不变,年产塑料制品20亿件,</div><div>主要为一次性塑料用品。全厂员工40人,实行两班16小时工作制,年有</div><div>效工作日为300天,年运行时数4800小时。</div><div>(二)建设过程及环保审批情况</div><div>项目于2020年7月委托江苏绿源工程设计研究有限公司编制了《塑料</div><div>制品迁建项目环境影响报告表》,于2020年10月27日通过苏州市生态环</div><div>境局审批(苏行审环评[2020]10268号)。2020年11月建成。</div><div>(三)投资情况</div><div>项目总投资500万元人民币,其中环保投资50万元,占总投资比例</div><div>10%。</div><div>(四)验收范围</div><div>本次对张家港励晟塑胶制品有限公司塑料制品迁建项目(苏行审环评</div><div>第1页共4页</div><div>[2020]10268号)进行验收。</div><div>二、工程变动情况</div><div>依据环评报告表、环评批复等材料,对项目实际建设相关内容进行</div><div>梳理,项目实际生产设备较环评增加4台混料机、2台冲床,减少2台手</div><div>套机、1台流延机。设备增加或减少均不导致废气、废水污染物增加,因</div><div>此不属于重大变动。</div><div>三、环境保护设施建设情况</div><div>(一)废水</div><div>本项目生活污水汇入村里集中化粪池,由村里负责集中托运;本项</div><div>目造粒工段使用的冷却水通过冷却塔循环回用,不外排。</div><div>(二)废气</div><div>本项目吹膜、流延、封口、造粒产生的有机废气和颗粒物经集气罩</div><div>收集后经1套干式过滤(过滤棉)+活性炭吸附装置处理后通过一根15米</div><div>高排气筒排放。</div><div>(三)噪声</div><div>本项目噪声主要为生产设备运行时产生的噪声,采取的噪声治理措</div><div>施由设施布置于室内,厂区四周墙体采用实体墙,噪声源强相对较高的</div><div>设备加装消声减振器或者隔声屏障,日常生产时加强科学管理。</div><div>(四)固体废物</div><div>本项目产生的固废主要包括:边角料、废活性炭、废过滤棉。</div><div>1、一般工业固废中部分边角料回用于生产,其余全部外售综合利用。</div><div>2、危险固废:委托有资质单位处理。</div><div>3、生活垃圾委托环卫部门处置。</div><div>四、环境保护设施调试效果</div><div>苏州捷盈环境检测有限公司于2022年10月24日-25日对项目进行了现</div><div>场验收监测。验收监测期间生产正常,满足规范化监测的要求。</div><div>第2页共4页</div><div>(一)污染物排放情况</div><div>1、废气</div><div>本项目废气排放均满足《合成树脂工业污染物排放标准》</div><div>(GB31572-2015)、江苏省《大气污染物综合排放标准》(DB32/4041-</div><div>2021)标准限值要求。</div><div>2、厂界噪声</div><div>本项目厂界环境噪声各测点昼、夜间等效声级值均满足《工业企业</div><div>厂界环境噪声排放标准》(GB12348-2008)2类标准限值要求。</div><div>3、固废</div><div>本项目固体废物均得到有效处置,实现“零排放”。</div><div>4、卫生防护距离</div><div>本项目以造粒车间为界设置的100m、以生产车间为界设置的50m卫生</div><div>防护距离内无环境敏感目标。</div><div>5、排污相关</div><div>本项目排放的污染物总量满足环评批复的要求。排污许可本项目已于</div><div>2023年4月28日取得了排污许可。</div><div>五、验收结论</div><div>项目执行了环保“三同时”制度,落实了环评及批复要求的污染防治</div><div>措施,环保设施运行正常,主要污染物达标排放。对照《建设项目竣工</div><div>环境保护验收暂行办法》,验收工作组认为:本项目废水、废气、噪声、</div><div>固废等污染设施措施满足环评及批复的要求,同意通过本项目竣工环境</div><div>保护“三同时”验收。</div><div>六、后续要求</div><div>1、进一步加强固物的规范化管理,确保每批次可追溯;</div><div>2、进一步加强废气废水治理设施的管理,确保持续稳定正常的运行;</div><div>3、进一步加强规范化的监测,确保排放的污染物稳定达标;</div><div>第3页共4页</div><div>4、进一步强化公司的环境安全应急预案,杜绝因意外事故诱发的环</div><div>境(安全)二次污染。</div><div>七、验收人员信息</div><div>验收人员名单附后。</div><div>张家港励晟塑胶制品有限公司</div><div>2023年7月27日</div><div>第4页共4页</div></div></div></div>
  1398. """
  1399. _tree = html_to_tree(html_content)
  1400. _pd = Html2KVTree(html_content)
  1401. _pd.print_tree(_pd.tree,"-|")
  1402. list_kv = _pd.extract_kv("建设单位")
  1403. print(list_kv)
  1404. #获取预处理后的所有句子,该句子与kv值对应
  1405. print(_pd.get_tree_sentence())
  1406. # soup = BeautifulSoup(html_content,"lxml")
  1407. # table_tree = table_to_tree(soup)
  1408. # print(json.dumps(table_tree,ensure_ascii=False))