Python爬取并分析招聘网站薪资分布:从数据抓取到可视化洞察

140 阅读7分钟

在求职季,薪资数据是求职者最关心的指标之一。通过爬取招聘网站数据,我们可以直观了解不同岗位、城市的薪资分布,为职业规划提供数据支撑。本文将用通俗易懂的方式,带你完成一个完整的薪资分析项目,涵盖爬虫开发、数据清洗、可视化分析等环节。

免费python编程教程:pan.quark.cn/s/2c17aed36…

一、项目目标与工具准备

1.1 明确分析目标

我们以BOSS直聘拉勾网为例,爬取以下数据:

  • 岗位名称(如Python开发、数据分析)
  • 薪资范围(如15k-25k)
  • 工作地点(北京、上海等)
  • 工作经验要求(1-3年、3-5年)
  • 学历要求(本科、硕士)

1.2 开发环境配置

  • Python版本:3.8+(推荐使用Anaconda管理环境)

  • 核心库

    pip install requests pandas matplotlib seaborn fake-useragent
    

    转存失败,建议直接上传图片文件

  • 辅助工具

    • Chrome开发者工具(抓包分析)
    • 代理IP池(如站大爷IP代理)

二、爬虫开发:突破反爬机制

2.1 目标网站分析

以BOSS直聘为例,其薪资数据通过接口返回JSON格式,URL示例:

https://www.****.com/wapi/zpboss/h5/marketpay/statistics.json?positionId=100109

转存失败,建议直接上传图片文件

通过Chrome开发者工具的Network面板,可找到数据接口。

2.2 发送请求与反爬策略

关键代码

import requests
from fake_useragent import UserAgent

def get_salary_data(position_id):
    url = "https://www.***.com/wapi/zpboss/h5/marketpay/statistics.json"
    headers = {
        "User-Agent": UserAgent().random,
        "Referer": "https://www.***.com/"
    }
    params = {
        "positionId": position_id,
        "cityId": "0"  # 全国数据
    }
    response = requests.get(url, headers=headers, params=params)
    return response.json()

转存失败,建议直接上传图片文件

反爬技巧

  1. 随机User-Agent:使用fake_useragent库模拟不同浏览器。
  2. 代理IP轮换:通过代理池(如站大爷IP代理)每请求更换IP。
  3. 请求间隔:添加随机延迟(如time.sleep(random.uniform(1, 3)))。

2.3 数据解析与存储

从返回的JSON中提取薪资分位值(如25%、50%、75%分位):

def parse_salary(json_data):
    salary_data = json_data["zpData"]["salaryByPoints"]
    results = []
    for item in salary_data:
        results.append({
            "分位": item["name"],
            "薪资(k)": item["salary"]
        })
    return results

转存失败,建议直接上传图片文件

将数据存储为CSV文件:

import pandas as pd

data = parse_salary(get_salary_data("100109"))  # Python开发岗位
df = pd.DataFrame(data)
df.to_csv("python_salary.csv", index=False, encoding="utf-8")

转存失败,建议直接上传图片文件

三、数据清洗与预处理

3.1 薪资范围标准化

原始薪资数据可能为字符串(如"15k-25k"),需转换为数值范围:

def clean_salary(salary_str):
    if "-" in salary_str:
        min_salary, max_salary = salary_str.split("-")
        min_salary = float(min_salary.replace("k", "")) * 1000
        max_salary = float(max_salary.replace("k", "")) * 1000
        return (min_salary + max_salary) / 2  # 返回中位数
    else:
        return float(salary_str.replace("k", "")) * 1000

# 应用清洗函数
df["中位数薪资"] = df["薪资范围"].apply(clean_salary)

转存失败,建议直接上传图片文件

3.2 分类变量编码

将学历、工作经验等分类变量转换为数值:

from sklearn.preprocessing import LabelEncoder

le_edu = LabelEncoder()
df["学历编码"] = le_edu.fit_transform(df["学历"])

# 或使用One-Hot编码(适合无序分类)
df = pd.get_dummies(df, columns=["工作经验"])

转存失败,建议直接上传图片文件

四、可视化分析:揭示薪资分布规律

4.1 薪资箱线图:观察分布离散程度

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(10, 6))
sns.boxplot(x="城市", y="中位数薪资", data=df)
plt.title("不同城市Python开发薪资分布")
plt.ylabel("薪资(元)")
plt.xticks(rotation=45)
plt.show()

转存失败,建议直接上传图片文件

解读:箱线图可显示中位数、四分位数及异常值,帮助识别薪资离散程度。

4.2 薪资热力图:城市与经验交叉分析

pivot_table = df.pivot_table(
    values="中位数薪资",
    index="城市",
    columns="工作经验",
    aggfunc="mean"
)

plt.figure(figsize=(12, 8))
sns.heatmap(pivot_table, annot=True, fmt=".0f", cmap="YlGnBu")
plt.title("城市与工作经验交叉薪资热力图")
plt.xlabel("工作经验")
plt.ylabel("城市")
plt.show()

转存失败,建议直接上传图片文件

解读:热力图直观展示不同城市、经验下的薪资差异,例如北京3-5年经验薪资显著高于其他城市。

4.3 薪资趋势线:经验与薪资关系

plt.figure(figsize=(10, 6))
sns.lmplot(
    x="工作经验年限",
    y="中位数薪资",
    data=df,
    height=6,
    aspect=1.5,
    scatter_kws={"s": 50}
)
plt.title("工作经验与薪资关系趋势线")
plt.xlabel("工作经验(年)")
plt.ylabel("薪资(元)")
plt.show()

转存失败,建议直接上传图片文件

解读:趋势线显示薪资随经验增长呈线性上升,但5年以上经验增速放缓。

五、进阶分析:预测模型构建

5.1 特征选择与数据分割

from sklearn.model_selection import train_test_split

features = ["学历编码", "工作经验年限", "城市编码"]  # 需提前编码城市
X = df[features]
y = df["中位数薪资"]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

转存失败,建议直接上传图片文件

5.2 线性回归模型

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X_train, y_train)

# 评估模型
score = model.score(X_test, y_test)
print(f"模型R²得分:{score:.2f}")

转存失败,建议直接上传图片文件

输出示例

模型R²得分:0.78

转存失败,建议直接上传图片文件

解读:R²=0.78表示模型可解释78%的薪资变异,学历、经验对薪资影响显著。

六、常见问题Q&A

Q1:被网站封IP怎么办?

A:立即启用备用代理池,建议使用住宅代理(如站大爷IP代理),配合每请求更换IP策略。同时检查请求频率是否过高(建议≥3秒/次),并模拟真人操作节奏(如随机延迟、随机浏览)。

Q2:如何获取多个城市的薪资数据?

A:在请求参数中添加cityId字段(如cityId=101010100代表北京),或通过循环遍历城市ID列表实现批量抓取。

Q3:爬取的数据可以商用吗?

A:需遵守《反不正当竞争法》及网站用户协议。建议仅用于个人学习研究,避免直接商用或传播原始数据。

Q4:如何处理动态加载的薪资数据?

A:部分网站(如拉勾网)通过Ajax加载数据,需分析接口URL(如https://www.lagou.com/jobs/positionAjax.json),并模拟POST请求携带必要参数(如pn=1表示第1页)。

Q5:代理IP质量差导致封号怎么办?

A:选择支持“独享IP”或“纯净IP池”的服务商(如易兹网络代理),避免使用被污染的IP。同时配合设备指纹修改工具(如Multilogin)隐藏硬件信息。

七、总结与扩展

通过本文,你已掌握:

  1. 使用Python爬取招聘网站薪资数据
  2. 数据清洗与标准化方法
  3. 可视化分析薪资分布规律
  4. 构建简单预测模型

扩展方向

  • 爬取更多网站(如前程无忧、猎聘)进行对比分析
  • 加入公司规模、行业等维度深化分析
  • 使用更复杂的机器学习模型(如随机森林)提升预测精度