- 抓取数据
Boss 直聘网站大家应该都非常清楚了,就不做过多介绍了,直接进入主题。
- 页面分析
在 Boss 直聘的官网上搜索 Python,可以看到浏览器的 URL 变为如下:
把该地址复制到 Postman 尝试访问,发现无法得到正确的返回:
此时,再次回到浏览器,查看该请求下面的 headers,可以看到其中有一个 cookie,是很长的一串字符串,我们拷贝这个 cookie 到 Postman 中,再次请求:
成功了,看来 Boss 直聘网也只是做了简单的 cookies 验证。
- BeautifulSoup 使用
下面就是解析 HTML 数据了,我比较习惯用 BeautifulSoup 这个库来解析。
from bs4 import BeautifulSoup
import requests
'''
python学习交流群:1136201545更多学习资料可以加群获取
'''
url = 'https://www.zhipin.com/job_detail/?query=python&city=101010100'
res = requests.get(url, headers=header).text
print(res)
content = BeautifulSoup(res, "html.parser")
ul = content.find_all('ul')
print(ul[12])
可以使用 BeautifulSoup 的 find 函数来查找 HTML 的元素标签,个人觉得还是挺方便的,虽然说速度上比 xpath 要慢,但是书写简单呀。
- 编写代码
我们通过分析 HTML 网页可以知道,所有的工作信息都是保存在 ul 这个标签中的,我们可以通过上面的代码拿到页面中所有的 ul 标签,find_all 返回的是一个列表,然后再查看,工作具体位于第几个 ul 中,这样就拿到具体的工作信息了。
如图中所示,我们需要抓取红框中的信息,主要分为四部分。
- python:可以得到该 job 具体页面地址
- 10-15K:每个 job 的薪资
- 柯莱特集团:招聘公司名称
- 北京 朝阳区 望京|3-5年|学历不限:该 job 的详情信息
对于前三个信息,还是比较好抓取的。
job_details_uri = job.find('h3', attrs={'class': 'name'}).find('a')['href']
job_company = job.find('div', attrs={'class': 'company-text'}).find('h3', attrs={'class': 'name'}).find('a').text
job_salary = job.find('h3', attrs={'class': 'name'}).find('span', attrs={'class': 'red'}).text
对于 job 的详情信息,需要用到正则表达式来分割字符串,我们先来看下该部分的原始形式:
又可以把该部分切分成三块,site、year 和 edu。可以使用正则的 group 特性,帮助我们完成切分,最后我写的正则如下:
rege = r'<p>([一-龥 ]+)<em class="vline"></em>([d+-年]+|[一-龥]+)<em class="vline"></em>([一-龥]+)'
正则表达式的具体写法这里就不说了,不熟悉的可以自行查找下。
下面把这部分代码整合到一起:
for job in jobs:
job_dict = {}
job_details_uri = job.find('h3', attrs={'class': 'name'}).find('a')['href']
job_company = job.find('div', attrs={'class': 'company-text'}).find('h3', attrs={'class': 'name'}).find('a').text
job_salary = job.find('h3', attrs={'class': 'name'}).find('span', attrs={'class': 'red'}).text
job_details = str(job.find('p'))
print(job_details)
job_rege = re.match(rege, job_details)
job_dict['name'] = job_company
job_dict['uri'] = job_details_uri
job_dict['salary'] = job_salary
job_dict['site'] = job_rege.group(1)
job_dict['year'] = job_rege.group(2)
job_dict['edu'] = job_rege.group(3)
job_list.append(job_dict)
print(job_list)
由于我们最后还是得到了一个列表,里面包含字典,那么保存到 MongoDB 中应该是最为方便快捷的了。
mongo_collection.insert_many(job_list)
抓取多个页面
通过查看 Boss 网站的下一页源码可得到翻页 URL 的规律:
https://www.zhipin.com/c101010100/?query=python&page=
- c101010100:是城市代码,在我们这里就代表北京
- query:也很明显,就是我们的搜索关键字
- page:页数
于是我们最后整合代码如下:
def jobs(page):
for i in range(1, page + 1):
job_list = []
try:
print("正在抓取第 %s 页数据" % i)
uri = '/c101010100/?query=python&page=%s' % i
res = requests.get(config.url + uri, headers=header).text
content = BeautifulSoup(res, "html.parser")
ul = content.find_all('ul')
jobs = ul[12].find_all("li")
for job in jobs:
job_dict = {}
job_details_uri = job.find('h3', attrs={'class': 'name'}).find('a')['href']
job_company = job.find('div', attrs={'class': 'company-text'}).find('h3', attrs={'class': 'name'}).find(
'a').text
job_salary = job.find('h3', attrs={'class': 'name'}).find('span', attrs={'class': 'red'}).text
job_details = str(job.find('p'))
job_rege = re.match(rege, job_details)
job_dict['name'] = job_company
job_dict['uri'] = job_details_uri
job_dict['salary'] = job_salary
try:
job_dict['site'] = job_rege.group(1)
job_dict['year'] = job_rege.group(2)
job_dict['edu'] = job_rege.group(3)
except:
continue
job_list.append(job_dict)
print(job_list)
# save to mongoDB
try:
mongo_collection.insert_many(job_list)
except:
continue
time.sleep(1)
except:
continue
因为我上面的正在表达式并不能匹配所有的情况,所以使用 try…except 来忽略了其他不规则的情况。
岗位详情抓取
job 详情抓取完毕之后,开始抓取岗位详情,就是每个 job 的具体要求,毕竟知己知彼,百战不殆。
我们可以从 URI 中获得每个工作的详情页面地址,然后再拼接到 Boss 的主 URL 上:
https://www.zhipin.com/job_detail/a8920821a7487a901HJ43tm7EFY~.html
再来看下工作详情页面,所有的任职描述都在如下的 div 标签中:
没有什么特殊的,直接用 BeautifulSoup 解析即可。
def run_main():
jobs = job_collection.find()
for job in jobs:
print('获得工作的uri ', job['uri'])
get_details(job)
time.sleep(1)
def get_details(items):
base_url = config.url
url = base_url + items['uri']
company_name = items['name']
try:
res = requests.get(url, headers=header).text
content = BeautifulSoup(res, "html.parser")
text = content.find('div', attrs={'class': 'text'}).text.strip()
result = {'name': company_name, 'details': text}
details_collection.insert_one(result)
except:
raise
if __name__ == '__main__':
run_main()
最后我把爬取到的数据都保存到了 mlab 在线服务器中了,有需要的可以来这里获取
job_conn = MongoClient("mongodb://%s:%s@ds151612.mlab.com:51612/boss" % ('boss', 'boss123'))
job_db = job_conn.boss
job_collection = job_db.boss
details_collection = job_db.job_details
分析数据
Python 相关工作的数据已经拿到了,下面我们就来简单的做些分析,看看 Python 的工作前景到底怎么样
薪资水平
我们先来看看大家最关心的薪资水平吧
发现在我爬取的数据中,15-30K 的薪资是占据绝大多数的,次之的是 15-25K,总的来说,这个水平在北京只能算是中等吧。
当然我们也看到了,还是有一些企业在用高薪招 Python 工程师,那就是有9家企业报价到了 30-60K,这个薪资对于年入百万的大佬来说可能不算什么,但是我们相信对于我们绝大多数的普通码农来说那绝对是超级高薪了,所以我们不能放过对于这种高薪的追求,来看看这些岗位的技能要求吧
出高薪的企业是如下
对于我来说比较熟悉的企业还是蛮多的,映客、旷视、网易,京东都是大厂了,看来大厂就是财大气粗
再来看看他们对于职位的要求,高频词词云
基础组件 redis,MySQL,web 框架 tornado,flask 和 Django,这些技能看来是我们寻求高薪 Python 岗位的必备技能了。
而 “熟练,善于,掌握,精通” 等高频词语则告诉了我们,掌握一项技能,不能仅仅是知道了一些皮毛,我们要知其然,更要知其所以然。
工作年限
接下来再看看 Python 岗位对于工作年限上的要求又是怎样的呢
大部分的工作年限要求都是集中在了3-5年,看来这个工龄的码农们应该是比较吃香的,年轻力壮,而且可塑性强,关键是能加班啊!
学历要求
下面再来看看对于学历的要求
都说现在的企业招聘对于学历卡的严,但是在上图中能看出,大多数公司要求也不是特别高,只要你是本科毕业,最起码学历这关你是过的。
不过还是有一些企业要求是硕士,很有想法嘛,直接卡掉了 N 多的本科生,那么我们就来看看这些企业招收硕士的情况
确实有很多大厂,比如爱奇艺和旷视。但是其他的不仅公司名气不够,就连给的薪资也不够看啊,那个绿盟科技是什么鬼,难不成是薪资少写了一个零嘛!
所有任职要求词云
最后,我们再来看看,想要找一份 Python 相关的工作,哪些技能是必备的呢
.