Python数据可视化:浅谈数据分析岗

640?

作者 | 法纳斯特

来源 | 法纳斯特


讲道理,pyspider确实是一款优秀的爬虫框架,我们可以利用它快速方便地实现一个页面的抓取。


不过带来便捷性的同时,也有它的局限性,复杂页面不好爬取。


在本次的数据爬取中,BOSS直聘是成功使用pyspider。但拉勾网却不行,因为拉勾网的数据是Ajax加载的。


拉勾网岗位数据请求的网址是不变的,改变的是表单数据表单数据随着页数改变,请求方式为POST。这里没办法在pyspider里用循环遍历来获取每一页的数据。


也许是我对pyspider框架了解的不够,还达不到得心应手。所以最后拉勾网的爬取,采用平常的办法,在PyCharm中自行编写程序。


本次通过对BOSS直聘,拉勾网数据分析岗数据分析,了解数据分析岗的行业情况,也以此来了解从事数据分析所需要的技能。



/ 01 / 网页分析


640


获取BOSS直聘索引页信息,主要是岗位名称、薪资、地点、工作年限、学历要求,公司名称、类型、状态、规模。


本来一开始是想对详情页分析的,还可以获取详情页里的工作内容和工作技能需求。


然后由于请求太多,就放弃了。索引页有10页,1页有30个岗位,一个详情页就需要一个请求,算起来一共有300个请求。


我是到了第2页(60个请求),就出现了访问过于频繁的警告。


而只获取索引页信息的话,只有10个请求,基本上没什么问题,外加也不想去鼓捣代理IP,所以来点简单的。


到时候做数据挖掘岗位的数据时,看看放慢时间能否获取成功。


640


获取拉勾网索引页信息,主要是岗位名称、地点、薪资、工作年限、学历要求,公司名称、类型、状态、规模,工作技能,工作福利。


网页为Ajax请求,采用PyCharm编写代码,轻车熟路。



/ 02 / 数据获取


01 pyspider获取BOSS直聘数据


pyspider的安装很简单,直接在命令行pip3 install pyspider即可。


这里因为之前没有安装pyspider对接的PhantomJS(处理JavaScript渲染的页面)。


所以需要从网站下载下来它的exe文件,将其放入Python的exe文件所在的文件夹下。


最后在命令行输入pyspider all,即可运行pyspider。


在浏览器打开网址http://localhost:5000/,创建项目,添加项目名称,输入请求网址,得到如下图。


640


最后在pyspider的脚本编辑器里编写代码,结合左边的反馈情况,对代码加以改正。


640


脚本编辑器具体代码如下。


 
  

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Project: BOSS

from pyspider.libs.base_handler import *
import pymysql
import random
import time
import re

count = 0

class Handler(BaseHandler):
    # 添加请求头,否则出现403报错
    crawl_config = {'headers': {'User-Agent''Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}}

    def __init__(self):
        # 连接数据库
        self.db = pymysql.connect(host='127.0.0.1', user='root', password='774110919', port=3306, db='boss_job', charset='utf8mb4')

    def add_Mysql(self, id, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people):
        # 将数据写入数据库中
        try:
            cursor = self.db.cursor()
            sql = 'insert into job(id, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people) values ("%d", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")' % (id, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people);
            print(sql)
            cursor.execute(sql)
            print(cursor.lastrowid)
            self.db.commit()
        except Exception as e:
            print(e)
            self.db.rollback()

    @every(minutes=24 * 60)
    def on_start(self):
        # 因为pyspider默认是HTTP请求,对于HTTPS(加密)请求,需要添加validate_cert=False,否则599/SSL报错
        self.crawl('https://www.zhipin.com/job_detail/?query=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90&scity=100010000&industry=&position=', callback=self.index_page, validate_cert=False)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        time.sleep(random.randint(25))
        for i in response.doc('li > div').items():
            # 设置全局变量
            global count
            count += 1
            # 岗位名称
            job_title = i('.job-title').text()
            print(job_title)
            # 岗位薪水
            job_salary = i('.red').text()
            print(job_salary)
            # 岗位地点
            city_result = re.search('(.*?)<em class=', i('.info-primary > p').html())
            job_city = city_result.group(1).split(' ')[0]
            print(job_city)
            # 岗位经验
            experience_result = re.search('<em class="vline"/>(.*?)<em class="vline"/>', i('.info-primary > p').html())
            job_experience = experience_result.group(1)
            print(job_experience)
            # 岗位学历
            job_education = i('.info-primary > p').text().replace(' ''').replace(city_result.group(1).replace(' '''), '').replace(experience_result.group(1).replace(' '''),'')
            print(job_education)
            # 公司名称
            company_name = i('.info-company a').text()
            print(company_name)
            # 公司类型
            company_type_result = re.search('(.*?)<em class=', i('.info-company p').html())
            company_type = company_type_result.group(1)
            print(company_type)
            # 公司状态
            company_status_result = re.search('<em class="vline"/>(.*?)<em class="vline"/>', i('.info-company p').html())
            if company_status_result:
                company_status = company_status_result.group(1)
            else:
                company_status = '无信息'
            print(company_status)
            # 公司规模
            company_people = i('.info-company p').text().replace(company_type, '').replace(company_status,'')
            print(company_people + '\n')
            # 写入数据库中
            self.add_Mysql(count, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people)
        # 获取下一页信息
        next = response.doc('.next').attr.href
        if next != 'javascript:;':
            self.crawl(next, callback=self.index_page, validate_cert=False)
        else:
            print("The Work is Done")
        # 详情页信息获取,由于访问次数有限制,不使用
        #for each in response.doc('.name > a').items():
            #url = each.attr.href
            #self.crawl(each.attr.href, callback=self.detail_page, validate_cert=False)

    @config(priority=2)
    def detail_page(self, response):
        # 详情页信息获取,由于访问次数有限制,不使用
        message_job = response.doc('div > .info-primary > p').text()
        city_result = re.findall('城市:(.*?)经验', message_job)
        experience_result = re.findall('经验:(.*?)学历', message_job)
        education_result = re.findall('学历:(.*)', message_job)

        message_company = response.doc('.info-company > p').text().replace(response.doc('.info-company > p > a').text(),'')
        status_result = re.findall('(.*?)\d', message_company.split(' ')[0])
        people_result = message_company.split(' ')[0].replace(status_result[0], '')

        return {
            "job_title": response.doc('h1').text(),
            "job_salary": response.doc('.info-primary .badge').text(),
            "job_city": city_result[0],
            "job_experience": experience_result[0],
            "job_education": education_result[0],
            "job_skills": response.doc('.info-primary > .job-tags > span').text(),
            "job_detail": response.doc('div').filter('.text').eq(0).text().replace('\n'''),
            "company_name": response.doc('.info-company > .name > a').text(),
            "company_status": status_result[0],
            "company_people": people_result,
            "company_type": response.doc('.info-company > p > a').text(),
        }


获取BOSS直聘数据分析岗数据如下。


640


02 PyCharm获取拉勾网数据


 
  

import requests
import pymysql
import random
import time
import json

count = 0
# 设置请求网址及请求头参数
url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
headers = {
    'User-Agent''Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    'Cookie''你的Cookie值',
    'Accept''application/json, text/javascript, */*; q=0.01',
    'Connection''keep-alive',
    'Host''www.lagou.com',
    'Origin''https://www.lagou.com',
    'Referer''ttps://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=sug&fromSearch=true&suginput=shuju'
}

# 连接数据库
db = pymysql.connect(host='127.0.0.1', user='root', password='774110919', port=3306, db='lagou_job', charset='utf8mb4')


def add_Mysql(id, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people, job_tips, job_welfare):
    # 将数据写入数据库中
    try:
        cursor = db.cursor()
        sql = 'insert into job(id, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people, job_tips, job_welfare) values ("%d", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")' % (id, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people, job_tips, job_welfare);
        print(sql)
        cursor.execute(sql)
        print(cursor.lastrowid)
        db.commit()
    except Exception as e:
        print(e)
        db.rollback()


def get_message():
    for i in range(131):
        print('第' + str(i) + '页')
        time.sleep(random.randint(1020))
        data = {
            'first''false',
            'pn': i,
            'kd''数据分析'
        }
        response = requests.post(url=url, data=data, headers=headers)
        result = json.loads(response.text)
        job_messages = result['content']['positionResult']['result']
        for job in job_messages:
            global count
            count += 1
            # 岗位名称
            job_title = job['positionName']
            print(job_title)
            # 岗位薪水
            job_salary = job['salary']
            print(job_salary)
            # 岗位地点
            job_city = job['city']
            print(job_city)
            # 岗位经验
            job_experience = job['workYear']
            print(job_experience)
            # 岗位学历
            job_education = job['education']
            print(job_education)
            # 公司名称
            company_name = job['companyShortName']
            print(company_name)
            # 公司类型
            company_type = job['industryField']
            print(company_type)
            # 公司状态
            company_status = job['financeStage']
            print(company_status)
            # 公司规模
            company_people = job['companySize']
            print(company_people)
            # 工作技能
            if len(job['positionLables']) > 0:
                job_tips = ','.join(job['positionLables'])
            else:
                job_tips = 'None'
            print(job_tips)
            # 工作福利
            job_welfare = job['positionAdvantage']
            print(job_welfare + '\n\n')
            # 写入数据库
            add_Mysql(count, job_title, job_salary, job_city, job_experience, job_education, company_name, company_type, company_status, company_people, job_tips, job_welfare)


if __name__ == '__main__':
    get_message()


获取拉勾网数据分析岗数据如下。


640


这里的数据库都是自己在外面创建的,之前也用了好多回,就不贴代码细说了。



/ 03 / 数据可视化


01 城市分布图


640


640


岗位的分布情况,这里可以看出岗位大多都分布在东部地区,中部也有一些。


02 城市分布热力图


640


640


京津冀、长三角、珠三角密集度不相上下,成都重庆地区也有一小些需求。


可以说北上广深,这四个一线城市包揽了大部分的岗位需求。


03 工作经验薪水图


640


640


这里通过看箱形图的四分位及中间值,大致能看出随着工作年限的增长,薪资也是一路上升。


BOSS直聘里,1年以内工作经验的薪资,有个最高4万多的,这肯定是不合理的。


于是就去数据库看了下,其实那个岗位要求是3年以上,但实际给的标签却是1年以内。


所以说数据来源提供的数据的准确性很重要。


04 学历薪水图


640


640


总的来说「硕士」>「本科」>「大专」,当然大专、本科中也有高薪水的。


毕竟越往后能力就越重要,学历算是一个重要的加分项


05 公司状态薪水图


640


640


这里的数据没什么特点,就当了解下这些概念。


一个公司的发展,可以是从「天使轮」一直到「上市公司」,路途坎坷。


06 公司规模薪水图


640


640


正常来说,公司规模越大,薪水应该会越高。


毕竟大厂的工资摆在那里,想不知道都难。


不过这里没能体现出来差距,倒是发现人数最少的公司,最高工资给的不高,难不成是初期缺钱?


07 公司类型TOP10


640


640


数据分析岗主要集中在互联网行业,「金融」「地产」「教育」「医疗」「游戏」也有所涉及。


大部分岗位需求都集中第三产业上。


08 工作技能图


640


这个算是本次的重点,这些技能将会是日后学习的重点。


「数据挖掘」「SQL」「BI」「数据运营」「SPSS」「数据库」「MySQL」等等。


09 工作福利图


640


这里可以看出大部分重点都围绕着「五险一金」「福利多」「团队氛围好」「晋升空间大」「行业大牛领头」上。


要是哪家公司都具备了,那简直就是要上天。


不过你我都清楚,这是不存在的,就算可能存在,也只是别人家的公司而已~



/ 04 / 总结


最后贴两张BOSS直聘以及拉勾网薪水TOP20,以此来作为勉励。


01 BOSS直聘薪水TOP20


640


02 拉勾网薪水TOP20


640


毕竟我们不能仅仅当条咸鱼,我们要当就当一只有梦想的咸鱼!!!


公众号回复数据分析,即可获取源码。

◆ ◆ ◆  ◆ ◆

数据森麟
长按二维码关注我们





数据森麟公众号的交流群已经建立,许多小伙伴已经加入其中,感谢大家的支持。大家可以在群里交流关于数据分析&数据挖掘的相关内容,还没有加入的小伙伴可以通过扫描下方管理员二维码,让管理员帮忙拉进群,期待大家的加入。


管理员二维码:


猜你喜欢

● 

● 

● 

● 

   ● 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值