Python爬取前程无忧和拉勾数据分析岗位并分析

一、明确需求

分析数据分析岗位的招聘情况,包括地区分布、薪资水平、职位要求等,了解最新数据分析岗位的情况。 环境:python 3.6 设计的工具:Tableau工具、pandas

二、数据采集

首先编写爬虫,这里主要是爬取前程无忧和拉勾网,直接上前程无忧的代码:

关于前程无忧爬虫代码,网上有很多教程,不过大部分只取了地区、职位、工资和日期这几个字段, 没有涉及到岗位要求和岗位职责,因为要了解职位的需求以及后面方便画词云,我就自己写了一个代码。 说一下拉勾和前程无忧两者的区别,前程无忧爬了2000页,不过大概只有前24页是跟数据分析有关的岗位, 拉勾网的数据量比较少,全国主要城市爬下来,一共也才2000多条,而且基本集中在北京上海杭州。 调整一下前程无忧爬虫格式跟拉勾一样,把两个表格合并起来一起分析。

# -*- coding:utf-8 -*-  
import urllib  
import re,codecs  
import time,random  
import requests  
from lxml import html  
from urllib import parse  
  
key='数据分析'  
key=parse.quote(parse.quote(key))  
headers={'Host':'search.51job.com',  
        'Upgrade-Insecure-Requests':'1',  
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}  
def get_links(page):  
    url ='http://search.51job.com/list/000000,000000,0000,00,9,99,'+key+',2,'+ str(page)+'.html'  
    r= requests.get(url,headers,timeout=10)  
    s=requests.session()  
    s.keep_alive = False  
    r.encoding = 'gbk'  
    reg = re.compile(r'class="t1 ">.*? <a target="_blank" title=".*?" href="(.*?)".*? <span class="t2">', re.S)  
    links = re.findall(reg, r.text)  
    return links  
#多页处理,下载到文件  
def get_content(link):  
    r1=requests.get(link,headers,timeout=10)  
    s=requests.session()  
    s.keep_alive = False  
    r1.encoding = 'gbk'  
    t1=html.fromstring(r1.text)  
    try:  
        job=t1.xpath('//div[@class="tHeader tHjob"]//h1/text()')[0]  
        company = t1.xpath('//p[@class="cname"]/a/text()')[0]  
        print(company)  
        label=t1.xpath('//p[@class="t2"]/span/text()')  
        education=t1.xpath('//div[@class="t1"]//span[2]/text()')[0]  
        salary = re.findall(re.compile(r'<span class="lname">.*?<strong>(.*?)</strong>',re.S),r1.text)[0]  
        area = t1.xpath('//div[@class="tHeader tHjob"]//span[@class="lname"]/text()')[0]  
        companytype=t1.xpath('//p[@class="msg ltype"]/text()')  
        workyear=t1.xpath('//div[@class="t1"]//span[1]/text()')[0]  
        describe = re.findall(re.compile(r'<div class="bmsg job_msg inbox">(.*?)任职要求',re.S),r1.text)  
        require =  re.findall(re.compile(r'<div class="bmsg job_msg inbox">.*?任职要求(.*?)<div class="mt10">',re.S),r1.text)  
        try:  
            file = codecs.open('51job.xls', 'a+', 'utf-8')  
            item = str(company)+'\t'+str(job)+'\t'+str(education)+'\t'+str(label)+'\t'+str(salary)+'\t'+str(companytype)+'\t'+str(workyear)+'\t'+str(area)+'\t'+str(workyear)+str(describe)+'\t'+str(require)+'\n'  
            file.write(item)  
            file.close()  
            return True  
        except Exception as e:  
            print(e)  
            return None  
        #output='{},{},{},{},{},{},{},{}\n'.format(company,job,education,label,salary,area,describe,require)  
        #with open('51job.csv', 'a+', encoding='utf-8') as f:  
            #f.write(output)  
    except:  
        print('None')  
  
for  i in range(1,2000):  
    print('正在爬取第{}页信息'.format(i))  
    try:  
        #time.sleep(random.random()+random.randint(1,5))  
        links=get_links(i)  
        for link in links:  
            get_content(link)  
            #time.sleep(random.random()+random.randint(0,1))  
    except:  
        continue  
        print('有点问题')   
 

三、数据探索和预处理:

数据爬取完了,大概有十万条数据,看起来还不错。 image 然而问题来了:

  • 1.数据有重复,需要去重。

  • 2.岗位不是全部是数据分析,也有招聘店长、销售、运营之类的岗位,需要去除无关数据。

利用pandas模块,短短几行代码就可以实现了,而且数据很快。  

# -*- coding: UTF-8 -*-  
import pandas as pd  
import numpy as np  
  
data=pd.read_excel('51joball.xlsx',sheet_name='Sheet1',header=0)  
df=pd.DataFrame(data)  
df=df[True- df.公司.duplicated()]#去重  
df=df[df.职位.str.contains(r'.*?数据.*?|.*?分析.*?')]#提取包含数据或者分析的岗位  
df.to_excel('new51job.xlsx')  

接下来还有一个问题需要处理,就是数据规范化,薪资待遇这栏,有的是千/月,有的是万每年,有的是元/天,有的是K每月,不规划化,无法进行分析。地区这一栏,有的有区,有的没区,我们规划到城市这个级别就好了。这里利用xlrd模块读取Excel表格,当然换成pandas一样也可以。

#coding:utf8  
import xlrd  
import codecs  
import re  
#加载Excel数据,获得工作表和行数  
def load_from_xlsx(file):  
    data = xlrd.open_workbook(file)  
    table0 = data.sheet_by_name('Sheet1')  
    nrows = table0.nrows  
    return table0, nrows  
#利用正则表达式提取月薪,把待遇规范成千/月的形式  
def get_salary(salary):  
    if '-'in salary: #针对1-2万/月或者10-20万/年的情况,包含-  
        low_salary=re.findall(re.compile('(\d*\.?\d+)'),salary)[0]  
        high_salary=re.findall(re.compile('(\d?\.?\d+)'),salary)[1]  
        if u'万' in salary and u'年' in salary:#单位统一成千/月的形式  
            low_salary = float(low_salary) / 12 * 10  
            high_salary = float(high_salary) / 12 * 10  
        elif u'万' in salary and u'月' in salary:  
            low_salary = float(low_salary) * 10  
            high_salary = float(high_salary) * 10  
    else:#针对20万以上/年和100元/天这种情况,不包含-,取最低工资,没有最高工资  
        low_salary = re.findall(re.compile('(\d*\.?\d+)'), salary)[0]  
        high_salary=""  
        if u'万' in salary and u'年' in salary:#单位统一成千/月的形式  
            low_salary = float(low_salary) / 12 * 10  
        elif u'万' in salary and u'月' in salary:  
            low_salary = float(low_salary) * 10  
        elif u'元'in salary and u'天'in salary:  
            low_salary=float(low_salary)/1000*21#每月工作日21天  
    return low_salary,high_salary  
  
def main():  
    data = load_from_xlsx(r'new51job.xlsx')  
    table, nrows = data[0], data[1]  
    print('一共有{}行数据,开始清洗数据'.format(nrows))  
    for i in range(1,nrows):  
        id=table.row_values(i)[0]  
        company=table.row_values(i)[1]  
        position = table.row_values(i)[2]  
        education = table.row_values(i)[3]  
        welfare = table.row_values(i)[4]  
        salary=table.row_values(i)[5]  
        area = table.row_values(i)[6][:2]#地区取到城市,把区域去掉  
        companytype = table.row_values(i)[7]  
        companysize = table.row_values(i)[8]  
        field = table.row_values(i)[9]  
        experience = table.row_values(i)[10]  
        responsibility = table.row_values(i)[11]  
        requirement = table.row_values(i)[12]  
        if salary:#如果待遇这栏不为空,计算最低最高待遇  
            getsalary=get_salary(salary)  
            low_salary=getsalary[0]  
            high_salary=getsalary[1]  
        else:  
            low_salary=high_salary=""  
        print('正在写入第{}条,最低工资是{}k,最高工资是{}k'.format(i,low_salary,high_salary))  
        output = '{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n'.format(id, company, position, education, welfare,low_salary, high_salary, area, companytype,companysize, field, experience, responsibility,requirement)  
        f=codecs.open('51jobanaly.xls','a+')  
        f.write(output)  
        f.close()  
if __name__=='__main__':  
    main()  

看看清洗之后的效果 image

四、数据可视化与分析

1.各地区招聘公司数量和平均待遇。

用tebleau生成地理图十分方便强大。可以看出不论是招聘公司的数据还是平均待遇水平主要都是北上广深杭州占优势。成都紧随其后。  ![image](https://raw.githubusercontent.com/lbship/lbship.github.io/master/img/51job3.png)  

2.公司类型

可以看出招聘的公司主要是民营企业和一些创业公司为主。 image

3.公司规模和公司领域

可以看出招聘公司的规模在50-500人规模为主,招聘的领域主要是互联网公司,金融紧随其后。 image

4.经验和学历要求

学历这里主要是大专本科为主,要求不算很高。 image

5.岗位要求和岗位职责

直接生成现在最流行的词云 image image