爬虫-广东人事考试网
广东人事考试网登录网址:https://ggfw.gdhrss.gov.cn/sydwbk/index.do
查看报名统计详情竟然不支持搜索和筛选,想看下报名人数还挺费劲,而且要查看岗位信息还要另外单独去查询。。
中间省略N字的吐槽,开搞
1.第一步先登录,打开查看报名统计详情
2.F12打开开发人员工具,点开网络,然后开始记录网络日志。
如上图点击查询按钮,会发现只有一个请求,请求方法POST,请求URL: https://ggfw.gdhrss.gov.cn/sydwbk/exam/details/spQuery.do
表单数据有四个bfa001、bab301、pages、rows
到这里思路就很清晰了,因为我们需要爬取全部数据,那就只需要bfa001、bab301这两项就好了,那就先试一下看看返回结果
1 import os 2 import sys 3 import requests 4 5 url = 'https://ggfw.gdhrss.gov.cn/sydwbk/exam/details/spQuery.do' 6 data = {'bfa001':'2210841','bab301':'05'} 7 headers = { 8 'user-agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36', 9 'Cookie':'JSESSIONID=AKnYcHe', # 这里复制自己的 10 } 11 r = requests.post(url,data=data, headers = headers) 12 13 with open('C:/Users/lenovo/Desktop/html.txt','w',encoding='utf-8') as f: 14 f.write(r.text) 15 os.system('C:/Users/lenovo/Desktop/html.txt')
返回json如下
{ "rows": [{ "aab004": "佛山市三水区公路养护中心", "aab019": 1, "aab119": 31, "aae036": 1648546541000, "bab301": "05", "bfe301": "2210841050001", "bfe3a4": "综合室工作岗位", "id": { "bfa001": "2210841", "bfz315": "87365" } }, { "aab004": "佛山市三水区西南街道社区卫生服务中心", "aab019": 3, "aab119": 3, "aae036": 1648546541000, "bab301": "05", "bfe301": "2210841050002", "bfe3a4": "临床医师", "id": { "bfa001": "2210841", "bfz315": "86909" } }, ... 中间省略 ... { "aab004": "佛山市三水区大塘镇宣传文体旅游办公室(佛山市三水区大塘镇教育办公室)", "aab019": 3, "aab119": 57, "aae036": 1648546541000, "bab301": "05", "bfe301": "2210841050128", "bfe3a4": "数学教师", "id": { "bfa001": "2210841", "bfz315": "87384" } } ], "total": 128 }
为了搞懂bfa001、bab301,那点开审查元素搜索一下,找到两项
从上图可看出bab301是城市代码
这里可以看出bfa001=2210841是固定值,结合json结果每一列对应含义都找到了
然后再完善一下,数据存到sqlite,完整代码如下:
#!/usr/bin/python #coding:utf-8 import re import requests import json import urllib import os import sys import random import time from datetime import datetime import sqlite3 from flask import Flask from flask_sqlalchemy import SQLAlchemy def Randomheader(): user_agent_list = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36',] UserAgent=random.choice(user_agent_list) return { 'user-agent':UserAgent, 'Cookie':'JSESSIONID=AKnYcHeRTlEK', # 这里复制自己的 'Host': 'ggfw.gdhrss.gov.cn', 'Origin': 'https://ggfw.gdhrss.gov.cn', 'Connection': 'keep-alive', } app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True db = SQLAlchemy(app) class Exam(db.Model): id = db.Column(db.String(255), primary_key=True) city = db.Column(db.String(255), primary_key=True) gwdm = db.Column(db.String(255), primary_key=True) zpdw = db.Column(db.String(255)) zpgw = db.Column(db.String(255)) pyrs = db.Column(db.Integer) bmrs = db.Column(db.Integer) tjsj = db.Column(db.DateTime) def __repr__(self): return f'{self.bmrs}\t{self.gwdm} {self.zpdw} {self.zpgw}' def get_exam_by_city(city_code): url = 'https://ggfw.gdhrss.gov.cn/sydwbk/exam/details/spQuery.do' data = {'bfa001':'2210841','bab301':city_code} r = requests.post(url,data=data, headers = Randomheader()) try: rows = json.loads(r.text) exam_list = [] for row in rows['rows']: exam = Exam.query.filter_by(id=row['id']['bfz315'],city=row['bab301'],gwdm=row['bfe301']).first() if exam: exam.bmrs=row['aab119'] exam.tjsj=datetime.fromtimestamp(row['aae036']/1000) else: exam = Exam(id=row['id']['bfz315'],city=row['bab301'], gwdm=row['bfe301'], zpdw=row['aab004'], zpgw=row['bfe3a4'], pyrs=row['aab019'], bmrs=row['aab119'], tjsj=datetime.fromtimestamp(row['aae036']/1000) ) if exam.id and exam.city and exam.gwdm: exam_list.append(exam) db.session.add_all(exam_list) db.session.commit() print(f"【{city_code}】爬取数目={rows['total']} 数据库数目={Exam.query.filter_by(city=city_code).count()}") except Exception as ex: print(repr(ex)) finally: db.session.close() if __name__ == '__main__': db.create_all() get_exam_by_city('99') # 省直 for i in range(21): time.sleep(10) # 防止访问过于频繁 get_exam_by_city('%02d'% (i+1))
3.至此,招聘信息和岗位报名人数拿到了,但是没有岗位详情。
招聘公告 附件有公开招聘岗位表
把Excel表下载下来导入到数据库,结合上面的Exam表来查询。
导入完整代码如下:
#!/usr/bin/python #coding:utf-8 import re import requests import json import urllib import os import sys import random import time from datetime import datetime import sqlite3 from flask import Flask from flask_sqlalchemy import SQLAlchemy import openpyxl app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True db = SQLAlchemy(app) class Job(db.Model): city_name = db.Column(db.String(255)) dwbh = db.Column(db.String(255), primary_key=True) gwdm = db.Column(db.String(255), primary_key=True) zpdw = db.Column(db.String(255)) zpgw = db.Column(db.String(255)) gwjj = db.Column(db.String(255)) gwdj = db.Column(db.String(255)) xlyq = db.Column(db.String(255)) xwyq = db.Column(db.String(255)) zyyq = db.Column(db.String(255)) gzjl = db.Column(db.String(255)) def __repr__(self): return f'{self.dwbh}\t{self.gwdm} {self.zpdw} {self.zpgw}' if __name__ == '__main__': db.create_all() wb = openpyxl.load_workbook('C:/Users/lenovo/Desktop/附件1:公开招聘岗位表.xlsx') sheet = wb.worksheets[0] row_index = 0 job_list = [] for row in sheet.iter_rows(): row_index = row_index + 1 row_str = str(row_index) job = Job( city_name = sheet['A'+row_str].value, dwbh = sheet['B'+row_str].value, gwdm = sheet['C'+row_str].value, zpdw = sheet['D'+row_str].value, zpgw = sheet['E'+row_str].value, gwjj = sheet['F'+row_str].value, gwdj = sheet['G'+row_str].value, xlyq = sheet['K'+row_str].value, xwyq = sheet['L'+row_str].value, zyyq = sheet['N'+row_str].value, gzjl = sheet['U'+row_str].value, ) if job.dwbh and job.gwdm and str.isdigit(job.gwdm): job_list.append(job) db.session.add_all(job_list) db.session.commit()
注意:Excel表第一行(就是合并单元格那行)删除后保存。
有需要的话,还可以先筛选Excel再导入。
数据库查询代码如下:
我这里只查看('省直','广州','佛山')三个考区,按岗位人均报名人数升序排序。
select b.city_name 考区,a.zpdw 招聘单位,a.zpgw 招聘岗位,a.gwdm 岗位代码,b.gwdj 岗位等级,b.gwjj 岗位简介,b.xlyq 学历要求,b.xwyq 学位要求,b.zyyq 专业要求,b.gzjl 工作经历,a.pyrs 聘用人数 ,a.bmrs 报名人数,a.tjsj 更新时间 from exam a,job b where a.gwdm=b.gwdm and b.city_name in ('省直','广州','佛山') order by a.bmrs/a.pyrs;