目前国内使用较多的招聘网站是boss直聘网,它有个优点就是可实时聊天沟通,免去了求职者胡乱海投,而且中间可能很多都没有招聘回复,对求职者非常友好。但海量的职位数据,我们有时也会蒙圈,不知道到底哪些职位才适合自己。 所以我们可能会想抓取一些职位回来分析。通过招聘职位数据,我们可以分析出自己所处行业的平均薪资,需求用户数,然后更好的制定自己的职业规划。
废话不多说,我们直接撸个小爬虫来实现这个简单的需求。(本文 源代码可加我索要, 也可以留下邮箱,我会定期批量发出)
为了完成本次需求,你需要了解或者熟悉初级的编程知识,如python语法,爬虫相关的python库等,对于技术细节我不会讲解太多,网上都有现成的,感兴趣的同学可以百度去搜一下教程
用到的技术如下(都是开源免费的技术):
Python3.7.7
playwright==1.15.3
lxml==4.6.3
以上几个包需要自己先安装好,实在不会的可加我询问。接下来我们一步步来实现吧!
进入boss直聘官网,现在可以免登录就可以浏览。假定我们的关注的行业是是北京-数据分析师。我们在网页中搜索,如图所示:

然后拉到下面可以看到,可以最多翻页10页,每页30条数据,所以我们就抓取这300条数据用来做个简单的分析。
playwright 就是我们小爬虫用到的一个重要工具了,它可以模拟人工做很多自动化的操作,比如打开链接,点击,移动等,反正基本上手工能做的操作,它都能实现。
先在文件开始导入用到的包:
1 import os 2 3 import time 4 5 import platform 6 7 import traceback 8 9 from ioimport StringIO 10 11 from lxmlimport etree 12 13 from playwright.sync_apiimport sync_playwright 14 15 接下来定义一些变量: 16 17 # 全局变量 18 19 totalCount =0 20 21 totalNewCount =0 22 23 page_count =0 24 25 got_blocked =False 26 27 city_name ='' 28 29 job_data_list = []# 用于保存所有的职位信息 30 31 # 保存用户的浏览器目录(Mac电脑的目录) 32 33 USER_DATA_BASE_DIR ='/Users/xiaowang/Documents/my/playwright-user-data/' 34 35 OUTPUT_DIR ='/Users/xiaowang/Documents/test_files/' 36 37 if platform.system() !='Darwin': 38 39 # Windows的目录 40 41 USER_DATA_BASE_DIR ='F:/projects/userdata/' 42 43 OUTPUT_DIR ='F:/projects/test_files/'
然后定义一个 解析函数,用于解析抓取到的职位列表页面,这里用到了不少知识点,如xpath,它就用来在html网页中准确定位元素的一个语言,而python的lxml库就实现了它,用起来也是相当的方便。
def parse_and_update_result_job(response): """ 解析职位列表 """ global totalCount, page_count, job_data_list content = response.body().decode("utf-8") tree = get_tree(content) divxp ="//div[@id='main']/div[@class='job-box']/div[@class='job-list']/ul/li" page_count =0 for n, iin enumerate(tree.xpath(divxp)): print('index: {}'.format(n+1)) jobName = get_first_text(i, "./div[@class='job-primary']/div[@class='info-primary']/div[@class='primary-wrapper']/div[@class='primary-box']/div[@class='job-title']/span[@class='job-name']/a") # /job_detail/0f5d152d524d87771nJ80tm8ElJR.html href = get_first(i, "./div[@class='job-primary']/div[@class='info-primary']/div[@class='primary-wrapper']/div[@class='primary-box']/div[@class='job-title']/span[@class='job-name']/a/@href") print('name: {}'.format(jobName)) job_id = href.split('/')[-1].split('.')[0] logo = get_first(i, "./div[@class='job-primary']/div[@class='info-primary']/div[@class='info-company']/a/img[@class='company-logo']/@src") brandName = get_first_text(i, "./div[@class='job-primary']/div[@class='info-primary']/div[@class='info-company']/div[@class='company-text']/h3[@class='name']/a") # /gongsi/3c1c53145ad9e62903Rz29U~.html company_href = get_first(i, "./div[@class='job-primary']/div[@class='info-primary']/div[@class='info-company']/div[@class='company-text']/h3[@class='name']/a/@href") company_id = company_href.split('.')[0].split('/')[-1] # 广州·天河区·珠江新城 area = get_first_text(i, ".//div[@class='job-title']/span[@class='job-area-wrapper']/span[@class='job-area']") salaryDesc = get_first(i, ".//div[@class='job-limit clearfix']/span[@class='red']/text()") gs_info = get_joined_str(i, ".//div[@class='info-company']/div[@class='company-text']/p//text()", '|') dic = { 'job_id': job_id, 'jobName': jobName, 'brandLogo': logo, 'brandName': brandName, 'company_id': company_id, 'city': area.split('·')[0], 'cityName': area.split('·')[0], 'area': area, 'href':'https://www.zhipin.com{}'.format(href), 'salaryDesc': salaryDesc, 'gs_info': gs_info } for k, vin dic.items(): print('{} -> {}'.format(k, v)) job_data_list.append(dic) print('成功抓取一条数据 \n') totalCount +=1 page_count +=1 print('--> 已经成功抓取总个数: {}'.format(totalCount)) print('\n')
接下来就是爬虫的主要部分了,涉及到playwright的功能,比如打开,导航,翻页等
class MainRunner(object): def __init__(self, p): super(MainRunner, self).__init__() self.browser = p.chromium# .launch(headless=False) self.max_page_job =10 # 职位最多抓取10页 def run_job(self): """ 开始运行 """ global got_blocked, page_count, job_data_list print('职位抓取...') url_tmpl ='https://www.zhipin.com/c101010100/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&page={p}&ka=page-{p}' site_name ='zhipin' user_data_dir = os.path.join(USER_DATA_BASE_DIR, '{}1'.format(site_name)) context =self.browser.launch_persistent_context( user_data_dir, headless=False, ) # 取第一个tab页面 page = context.pages[0] # 注册页面监控事件 page.on("response", lambda response: process_response_job(response)) # 先打开首页 page.goto('https://www.zhipin.com/') time.sleep(5) scrapyed_url = [] code ='c101010100' city_name ='北京' for pgin range(1, self.max_page_job +1): url = url_tmpl.format(code=code, p=pg) if urlin scrapyed_url: print('重复的url: {}, continue'.format(url)) continue print(u'{} page:{}, 抓取: {}'.format(city_name, pg, url)) try: page.goto(url) print('本页已打开完成...') except: print(u'* 打开网页遇到问题: {}'.format(traceback.format_exc())) scrapyed_url.append(url) print(u'end, {} page:{}, 抓取: {}'.format(city_name, pg, url)) time.sleep(5) if got_blocked: print('开始sleep.......') time.sleep(2 *3600) got_blocked =False # 开始写入excel文件 time.sleep(3) tmp_file_name ='bosszhipin_job_data_{}.csv'.format(int(time.time())) final_file = os.path.join(OUTPUT_DIR, tmp_file_name) print('最终输出文件: {}'.format(final_file)) with open(final_file, 'w')as f: f.write('名称,编号,公司,城市,区,薪水,公司情况,网址\n') for din job_data_list: row ='{},{},{},{},{},{},{},{}\n'.format(d['jobName'], d['job_id'], d['brandName'], d['city'], d['area'], d['salaryDesc'], d['gs_info'], d['href']) f.write(row) print('文件写入完成..') print('全部处理完成,直接退出.') page.close() if __name__ =='__main__': with sync_playwright()as p: runner = MainRunner(p) # 抓取职位 北京 数据分析师 runner.run_job()
上面的主程序的最后部分,是将抓取到的职位列表,写入一个本地的csv文件中,可以用WPS打开查看,当然细节的话你可以自己调整,比如转化薪水为年薪,然后算出平均年薪,这样对自己就有一个心理价位了。
这样爬虫就实现完成了,但这个简书的显示效果真是很不行,没能自动识别出编程语言,有要代码的可加我微信或留下邮箱。下面我就截图看看运行效果:

然后下面是导出的文件,接下来你就可以自己在excel中分析了,当然本程序可扩展的地方就太多了,看自己的喜好,比如保存到数据库中,将公司的信息分类保存,这样就能轻易分析出成千上万的职位了。当然了,本脚本只是用于简单的分析,请不要做一些违规的用途。

感兴趣的同学如有问题可一起讨论(newtime9244请备注说明来意,否则不会通过)本人做数据分析类的工作,欢迎一起学习。
欢迎评论