使用Python爬取Boss直聘的招聘数据并进行数据分析

前言

Boss直聘是一款广受欢迎的招聘平台,其中包含了丰富的岗位信息。作为数据分析人员或技术爱好者,通过爬虫获取这些数据可以帮助我们进一步理解市场需求。本次爬虫项目使用了Python的Selenium库,以模拟浏览器自动化操作来抓取Boss直聘的招聘信息。并将其可视化以获得对不同城市、公司规模、学历要求等维度的职位数据分析。我们将主要使用 pandasmatplotlibpyecharts 等库进行数据处理和可视化,最终生成一系列图表。

一、数据爬取

我们从招聘网站上爬取了以下字段:

  • 岗位名:职位名称
  • 工作地址:具体的工作地点
  • 薪资:职位薪资范围
  • 工作年限:要求的工作年限
  • 学历要求:最低学历要求
  • 公司名称:公司名称
  • 公司类型:公司性质(如外企、国企等)
  • 融资情况:公司融资阶段(如未融资、A轮、B轮等)
  • 公司规模:公司规模(如0-20人、100-500人等)
  • 岗位福利:公司提供的岗位福利(如五险一金、带薪年假等)
  • 城市:所在城市

实现多线程启动

start方法创建多个线程,并调用getData方法来实现数据抓取。每个线程负责爬取一个页面范围的

数据,以此来提高数据抓取效率。

from threading import Thread
import pandas as pd
from selenium.webdriver.edge.service import Service
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
class Boss(object):
    def start(self):
        threadList = []
        for i in range(14):  # 14个线程
            t = Thread(target=self.getData, args=(i,))
            t.start()
            print(f"线程{t.name}开始")
            time.sleep(10)  # 避免被封
            threadList.append(t)
        return threadList

数据抓取方法:getData

getData方法中,通过Selenium模拟访问Boss直聘的招聘页面。该方法会获取工作岗位的相关信息,包括岗位名、工作地址、薪资、公司类型等。

    def getData(self, i):
        service = Service("./driver/msedgedriver.exe")  # Edge驱动
        driver = webdriver.Edge(service=service)
        for i in range(10):  # 每个线程爬取10页数据
            driver.get(f"https://www.zhipin.com/web/geek/job?query=python&city=101040100&page={i+1}")
            driver.implicitly_wait(10)
            content = driver.find_elements(By.XPATH, '//div/ul/li[@class="job-card-wrapper"]')
            for massage in content:
                gwm = massage.find_element(By.XPATH, './div/a/div/span[@class="job-name"]').text
                gzdz = massage.find_element(By.XPATH, './div/a/div/span/span').text
                xz = massage.find_element(By.XPATH, './div/a/div/span[@class="salary"]').text
                gznx = massage.find_element(By.XPATH, './div/a/div/ul/li[1]').text
                xlyq = massage.find_element(By.XPATH, './div/a/div/ul/li[2]').text
                qymc = massage.find_element(By.XPATH, './div/div/div/h3/a').text
                # 公司类型、融资情况、公司规模等
                data = {
                    "岗位名": gwm,
                    "工作地址": gzdz,
                    "薪资": xz,
                    "工作年限": gznx,
                    "学历要求": xlyq,
                    "公司名称": qymc,
                }
                print(data)
                self.save(data)  # 调用保存方法
        driver.quit()

数据存储方法:save

save方法负责将抓取的数据保存至CSV文件。该方法首先检查文件是否存在,若存在则读取并将新数据追加,确保最终文件数据去重且结构完整。

    def save(self, data):
        filename = "boss职位.csv"
        df = pd.DataFrame([data])
        if pd.io.common.file_exists(filename):
            existing_df = pd.read_csv(filename)
            combined_df = pd.concat([existing_df, df], ignore_index=True)
            unique_df = combined_df.drop_duplicates(subset=['岗位名'], keep='first')
            unique_df.to_csv(filename, index=False, encoding='utf-8-sig')
        else:
            df.to_csv(filename, index=False, encoding='utf-8-sig')

启动爬虫

__main__部分启动整个程序,并调用startstop方法实现数据抓取的启动与终止。

if __name__ == '__main__':
    bs = Boss()
    threads = bs.start()
    bs.stop(threads)
  • 延时设置:为避免触发反爬机制,每个线程启动时加入了10秒的延时。
  • 数据去重:在保存数据时,通过去重避免了相同职位重复写入文件。

数据可视化可以帮助我们更清晰地了解数据的分布、趋势和关系。对Boss直聘的数据进行一系列图表绘制,包括地图、柱状图、饼图等,帮助我们更好地了解招聘市场的状况。

二、数据分析

数据预处理

首先,从CSV文件加载数据,检查是否存在缺失值,并进行数据清洗。对于空缺的公司规模字段,我们删除对应的数据行。

import pandas as pd

df = pd.read_csv('boss职位.csv')
df.drop(df[df['公司规模'].isnull()].index, inplace=True)

数据的分析与可视化

1. 城市岗位数量的地图分布

我们使用Pyecharts的Map图表绘制出全国主要城市的岗位数量分布,展示各地的招聘需求。

from pyecharts.charts import Map
from pyecharts import options as opt

df['城市'] = df['工作地址'].str.split('·', expand=True)[0]
map_chart = Map(init_opts=opt.InitOpts(width="1600px", height="600px"))
data = df.groupby('城市').size().reset_index().rename(columns={0: '数量'})
data['城市'] = data['城市'] + '市'
data = [list(z) for z in zip(data['城市'], data['数量'])]

map_chart.add("数据", data, "china-cities")
map_chart.set_global_opts(
    title_opts=opt.TitleOpts(title="热门城市岗位数量分布地图"),
    visualmap_opts=opt.VisualMapOpts(is_piecewise=False)
)
map_chart.render("热门城市岗位数量分布地图.html")

2. 热门城市的岗位数量柱状图

通过将城市按岗位数量排序并绘制柱状图,可以看到各城市的招聘岗位数量差异,方便我们了解招聘需求较多的地区。

from pyecharts.charts import Bar

bar = (Bar()
    .add_yaxis('岗位数量', city['岗位数量'].tolist(), color='blue')
    .add_xaxis(city['城市'].tolist())
    .set_global_opts(
        title_opts=opt.TitleOpts(title="热门城市工作岗位数量"),
        yaxis_opts=opt.AxisOpts(name="工作岗位数量", name_location="middle", name_gap=30),
        xaxis_opts=opt.AxisOpts(name="城市名称", name_location="middle", name_gap=30)
    )
)
bar.render("热门城市岗位数量.html")

3. 热门城市的平均薪资

我们计算各城市的平均薪资,通过柱状图呈现热门城市的薪资水平,便于观察不同城市之间的薪资差异。

data['平均薪资'] = (data['最低薪资'] + data['最高薪资']) / 2
data1 = data.groupby('城市').agg(
    平均最低薪资=('最低薪资', 'mean'),
    平均最高薪资=('最高薪资', 'mean'),
    平均薪资=('平均薪资', 'mean')
).reset_index()

bar = (Bar()
    .add_yaxis("下限", data1["平均最低薪资"].astype(int).tolist(), color='blue')
    .add_yaxis("上限", data1["平均最高薪资"].astype(int).tolist(), color="orange")
    .add_yaxis("平均薪资", data1["平均薪资"].astype(int).tolist())
    .add_xaxis(data1['城市'].tolist())
    .set_global_opts(
        title_opts=opt.TitleOpts(title="热门城市平均薪资"),
        yaxis_opts=opt.AxisOpts(name="平均薪资", name_location="middle", name_gap=50),
        xaxis_opts=opt.AxisOpts(name="城市名称", name_location="middle", name_gap=30)
    )
)
bar.render("热门城市平均薪资.html")

4. 岗位与学历的关系

通过对数据按学历要求进行分组,并使用饼图展示不同学历对应的岗位数量分布,可以直观地看到公司对不同学历的需求情况。

from pyecharts.charts import Pie

data3 = df.groupby('学历要求').size().sort_values(ascending=False).reset_index()
pie = Pie()
pie.add(
    "岗位与学历关系", 
    [list(z) for z in zip(data3['学历要求'].tolist(), data3[0].tolist())],
    radius=["40%", "75%"]
)
pie.set_global_opts(
    title_opts=opt.TitleOpts(title="岗位与学历关系")
)
pie.set_series_opts(
    label_opts=opt.LabelOpts(formatter="{b}: {c} ({d}%)")
)
pie.render("岗位与学历关系.html")

5. 工作年限与薪资的关系

公司对不同工龄的员工支付的薪资水平不同。我们通过自定义顺序展示各工作年限对应的平均薪资,形成清晰的薪资-工龄对比图。

custom_order = ['经验不限', '10年以上', '5-10年', '3-5年', '1-3年', '1年以内', '在校/应届']
data5 = data.groupby('工作年限').agg(平均薪资=('平均薪资', 'mean')).loc[custom_order].reset_index()

bar = (Bar()
    .add_yaxis("平均薪资", data5["平均薪资"].astype(int).tolist(), color="orange")
    .add_xaxis(data5['工作年限'].tolist())
    .set_global_opts(
        title_opts=opt.TitleOpts(title="工作年限与薪资的关系图"),
        yaxis_opts=opt.AxisOpts(name="平均薪资", name_location="middle", name_gap=50),
        xaxis_opts=opt.AxisOpts(name="工龄", name_location="middle", name_gap=30)
    )
)
bar.render("工作年限与薪资的关系图.html")

6. 薪资与学历关系

根据学历要求计算平均薪资,并通过柱状图展示学历与薪资之间的关系。

data3 = data2.groupby('学历要求').agg(
    平均薪资=('平均薪资', 'mean'),
).reset_index()
bar = Bar().add_xaxis(data3['学历要求'].tolist()).add_yaxis("平均薪资", data3["平均薪资"].astype(int).tolist(), color="green")

7. 工作年限与薪资关系

根据工作年限计算薪资,并绘制柱状图展示工作年限与薪资的关系。

data4 = data.groupby('工作年限').agg(
    平均薪资=('平均薪资', 'mean'),
).reset_index()
bar = Bar().add_yaxis("平均薪资", data4["平均薪资"].astype(int).tolist(), color="orange")

8. 公司规模与薪资关系

根据公司规模计算平均薪资,并展示公司规模与薪资的关系。

data6 = data.groupby('公司规模').agg(
    平均薪资=('平均薪资', 'mean'),
).reset_index()
bar = Bar().add_xaxis(data6['公司规模'].tolist()).add_yaxis("平均薪资", data6["平均薪资"].astype(int).tolist(), color="blue")

9. 融资情况与薪资关系

通过柱状图和折线图的组合展示不同融资情况的公司薪资分布。

data7 = data.groupby('融资情况').agg(
    数量=('融资情况', 'count'),
    平均薪资=('平均薪资', 'mean')
).reset_index()
bar = Bar().add_xaxis(data7['融资情况'].tolist()).add_yaxis("数量", data7['数量'].tolist(), color='blue', stack="stack1")
line = Line().add_xaxis(data7['融资情况'].tolist()).add_yaxis("平均薪资趋势", data7['平均薪资'].astype(int).tolist(), color='red', stack="stack1")
bar.overlap(line)

总结

python爬虫

本次项目更加熟悉如何使用Python和Selenium抓取Boss直聘的岗位信息,并将数据存储到CSV文件中。本次项目的核心在于多线程的实现以及数据存储的去重处理。

数据分析方面

对不同城市、不同学历要求、工作年限、公司规模等维度的岗位需求、薪资水平以及其他相关信息,且通过不同类型的图表(如柱状图、饼图、地图等)进行可视化展示,帮助直观了解各类信息的分布和趋势。最后,通过本次项目的实践,我掌握了如何用 pyecharts 创建多种类型的图表,还了解了如何处理和分析数据。这种能力对于数据可视化和分析工作非常有帮助

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值