srafa.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. # -*- coding: utf-8 -*-
  2. # @Author: privacy
  3. # @Date: 2022-07-07 12:59:42
  4. # @Last Modified by: privacy
  5. # @Last Modified time: 2022-07-18 13:50:02
  6. # import pdb
  7. import json
  8. import requests
  9. from requests.adapters import HTTPAdapter
  10. import pdfplumber
  11. from docx import Document
  12. path = "d:\\desktop\\社招简历模板.docx"
  13. class Social(object):
  14. """docstring for Social"""
  15. def __init__(self):
  16. super(Social, self).__init__()
  17. self.keywords = [
  18. '姓名',
  19. '性别',
  20. '出生日期',
  21. '一寸照片',
  22. '民族',
  23. '出生地',
  24. '政治面貌(加入时间)',
  25. '参加工作时间',
  26. '健康状况',
  27. '外语水平',
  28. '初始学历、专业',
  29. '最高学历、专业',
  30. '初始学历毕业院校及毕业时间',
  31. '最高学历毕业院校及毕业时间',
  32. '专业技术资格(取得时间)',
  33. '职业技能等级(取得时间)',
  34. '熟悉专业有何专长',
  35. '工作单位',
  36. '现任职务',
  37. '任职时间',
  38. '提职时间',
  39. '意向岗位',
  40. '联系电话',
  41. '学习经历',
  42. '起止时间',
  43. '学校',
  44. '专业',
  45. '学历',
  46. '学位',
  47. '研究方向',
  48. '是否全日制',
  49. '培训经历',
  50. '培训类型',
  51. '机构',
  52. '内容',
  53. '成绩',
  54. '证书名称',
  55. '工作经历',
  56. '职务',
  57. '部门',
  58. '证明人',
  59. '备注',
  60. '对报名岗位认识及工作设想',
  61. '自我评价及主要工作业绩',
  62. '获得职业资格证书情况',
  63. '获得日期',
  64. '名称',
  65. '证书编码/文号',
  66. '授予单位',
  67. '奖惩情况',
  68. '项目',
  69. '时间',
  70. '项目单位',
  71. '证明材料',
  72. '主要家庭成员及社会关系',
  73. '称谓',
  74. '出生年月',
  75. '政治面貌',
  76. '工作单位及职务',
  77. '其他情况说明',
  78. '诚信承诺',
  79. '社会招聘工作办公室资格审查意见'
  80. ]
  81. self.json_obj = self.get_translate()
  82. def get_translate(self):
  83. # 转译数据库字段名
  84. with open("./resources/translate.json", "r", encoding="utf-8") as ff:
  85. json_obj = json.load(ff)
  86. return json_obj
  87. def parse_line(self, line):
  88. result = []
  89. key = None
  90. for cell in line:
  91. if cell and ''.join(cell.split()) in self.keywords:
  92. key = ''.join(cell.split())
  93. elif cell and key:
  94. schema = {key:cell}
  95. result.append(schema)
  96. key = None
  97. return result
  98. # 解析word
  99. def parse_word_layout(self, path):
  100. result = []
  101. doc = Document(path)
  102. lo = {}
  103. for _table in doc.tables[:]:
  104. for i, row in enumerate(_table.rows[:]):
  105. row_content = []
  106. for cell in row.cells[:]:
  107. c = cell.text
  108. if c not in row_content:
  109. row_content.append(c)
  110. lo[len(lo.keys())] = row_content
  111. kwln = -1# 关键词行长度
  112. kwline = None# 关键词行
  113. for key in lo.keys():
  114. for val in lo[key]:# 通过全关键词,判断此行是否为关键词行
  115. if val and ''.join(val.split()) not in self.keywords:# 有非关键字元素,非关键词行,判断是否为关键词行元素
  116. perc = 0# 行内关键词数量
  117. for c in lo[key]:
  118. if c and (''.join(c.split()) in self.keywords):# 找到此行有关键词
  119. perc += 1
  120. if c and (''.join(c.split()) in self.keywords) and (perc > len(lo[key])/3):# 关键词数量超过1/3,判断此行非关键词行元素
  121. perc = 0# 清空行内关键词数
  122. result.extend(self.parse_line(lo[key]))# 添加并解析普通行级元素
  123. break
  124. else:# 关键词行元素
  125. if len(kwline) != len(lo[key]):
  126. break
  127. schema = dict()
  128. for key, val in zip(kwline, lo[key]):# 合并关键词行和行元素
  129. if key:
  130. schema[key] = val
  131. result.append(schema)
  132. break
  133. break
  134. else:
  135. # print("{}:此行为关键词行!".format(lo[key]))
  136. if len(lo[key])>2:
  137. try:
  138. kwline = [''.join(cell.split()) for cell in lo[key]]
  139. except Exception as e:
  140. kwline = lo[key]
  141. kwln = len(lo[key])
  142. return result
  143. # 解析pdf
  144. def parse_pdf_layout(self, path):
  145. result = []
  146. lo = {}
  147. with pdfplumber.open(path) as pdf:
  148. for page in pdf.pages:
  149. for table in page.extract_tables():
  150. for line in table:
  151. # lo[len(lo.keys())] = [cell for cell in line if cell]
  152. lo[len(lo.keys())] = line
  153. kwln = -1
  154. kwline = None
  155. for key in lo.keys():
  156. # pdb.set_trace()
  157. for val in lo[key]:# 通过全关键词,判断此行是否为关键词行
  158. if val and ''.join(val.split()) not in self.keywords:# 有非关键字元素,非关键词行,判断是否为关键词行元素
  159. # pdb.set_trace()
  160. for c in lo[key] or len(lo[key])!=kwln:
  161. # pdb.set_trace()
  162. if c and ''.join(c.split()) in self.keywords:# 非关键词行元素
  163. result.extend(self.parse_line(lo[key]))
  164. break
  165. else:# 关键词行元素
  166. schema = dict()
  167. for key, val in zip(kwline, lo[key]):
  168. if key:
  169. schema[key] = val if val else key
  170. result.append(schema)
  171. break
  172. break
  173. else:
  174. kwline = []
  175. for cell in lo[key]:
  176. if cell:
  177. kwline.append(''.join(cell.split()))
  178. else:
  179. kwline.append(cell)
  180. kwln = len(lo[key])
  181. return result
  182. # 格式化数据
  183. def formatter(self, datalist):
  184. result = dict()
  185. for d in datalist:
  186. if len(d) == 1:
  187. for key in d.keys():
  188. result[key] = d[key]
  189. else:
  190. for k in list(d.keys()):
  191. if k == "".join(d[k].split()):
  192. d.pop(k)
  193. if result.get(k):
  194. result[k].append(d)
  195. else:
  196. result[k] = [d]
  197. normal = self.json_obj["base"]
  198. itenormal = self.json_obj["base"]
  199. edunormal = self.json_obj["tal_his_edu"]
  200. jobnormal = self.json_obj["tal_his_job"]
  201. tranornal = self.json_obj["tal_training_experience"]
  202. cetnormal = self.json_obj["tal_vocational_qualification_certificate"]
  203. rewnormal = self.json_obj["tal_reward_punishment"]
  204. family = self.json_obj["tal_family_social_relation"]
  205. for key in normal.keys():
  206. if result.get(key):
  207. result[normal[key]] = result[key]
  208. result.pop(key)
  209. for idx in range(len(result['学习经历'])):
  210. for key in edunormal.keys():
  211. if result['学习经历'][idx].get(key):
  212. result['学习经历'][idx][edunormal[key]] = result['学习经历'][idx][key]
  213. result['学习经历'][idx].pop(key)
  214. for idx in range(len(result['工作经历'])):
  215. for key in jobnormal.keys():
  216. if result['工作经历'][idx].get(key):
  217. result['工作经历'][idx][jobnormal[key]] = result['工作经历'][idx][key]
  218. result['工作经历'][idx].pop(key)
  219. for idx in range(len(result['培训经历'])):
  220. for key in tranornal.keys():
  221. if result['培训经历'][idx].get(key):
  222. result['培训经历'][idx][tranornal[key]] = result['培训经历'][idx][key]
  223. result['培训经历'][idx].pop(key)
  224. for idx in range(len(result['获得职业资格证书情况'])):
  225. for key in cetnormal.keys():
  226. if result['获得职业资格证书情况'][idx].get(key):
  227. result['获得职业资格证书情况'][idx][cetnormal[key]] = result['获得职业资格证书情况'][idx][key]
  228. result['获得职业资格证书情况'][idx].pop(key)
  229. for idx in range(len(result['奖惩情况'])):
  230. for key in rewnormal.keys():
  231. if result['奖惩情况'][idx].get(key):
  232. result['奖惩情况'][idx][rewnormal[key]] = result['奖惩情况'][idx][key]
  233. result['奖惩情况'][idx].pop(key)
  234. for idx in range(len(result['主要家庭成员及社会关系'])):
  235. for key in family.keys():
  236. if result['主要家庭成员及社会关系'][idx].get(key):
  237. result['主要家庭成员及社会关系'][idx][family[key]] = result['主要家庭成员及社会关系'][idx][key]
  238. result['主要家庭成员及社会关系'][idx].pop(key)
  239. tit = {
  240. "基本信息":"base",
  241. "职业发展管理":"intent_job",
  242. "学习经历":"tal_his_edu",
  243. "工作经历":"tal_his_job",
  244. "项目经历":"tal_his_project",
  245. "培训经历":"tal_training_experience",
  246. "奖惩情况":"tal_reward_punishment",
  247. "语言能力":"tal_language",
  248. "获得职业资格证书情况":"tal_vocational_qualification_certificate",
  249. "专业技能":"tal_professional_tech_certificate",
  250. "主要家庭成员及社会关系":"tal_family_social_relation",
  251. "其他情况说明":"intro"
  252. }
  253. for key in tit.keys():
  254. if result.get(key):
  255. result[tit[key]] = result[key]
  256. result.pop(key)
  257. return result
  258. # 推送后端
  259. def push_back(self, result):
  260. url = "http://192.168.1.110:9999/talent/getResumeData"
  261. session = requests.Session()
  262. session.mount('http://', HTTPAdapter(max_retries = 3))
  263. try:
  264. headers = {
  265. 'contentType':'Application/json'
  266. }
  267. response = session.post(url=url, headers=headers, json={"ResumeData": result}, timeout=10)
  268. print(response.text)
  269. except Exception as e:
  270. print(e)
  271. def predict(self, path):
  272. if path.endswith(".docx"):
  273. result = self.formatter(self.parse_word_layout(path))
  274. self.push_back(result)
  275. print(self.formatter(self.parse_word_layout(path)))
  276. elif path.endswith(".pdf"):
  277. result = self.formatter(self.parse_pdf_layout(path))
  278. self.push_back(result)
  279. print(self.formatter(self.parse_pdf_layout(path)))
  280. if __name__ == '__main__':
  281. s = Social()
  282. s.predict(path)