用Python爬取51job招聘数据,手把手教你分析Python岗位薪资分布(附完整源码)
·
Python招聘数据深度分析:从爬取到洞察的完整实战指南
在当今数据驱动的就业市场中,掌握Python技能已成为许多技术岗位的基本要求。但对于求职者而言,仅仅知道Python语法远远不够——了解市场真实需求、薪资分布和技能趋势同样重要。本文将带你从51job招聘数据的获取开始,一步步完成数据清洗、分析和可视化全过程,最终生成一份具有商业洞察力的分析报告。
1. 数据获取与初步处理
1.1 构建稳健的爬虫系统
现代招聘网站通常都有反爬机制,我们需要构建一个既能获取数据又不违反网站政策的爬虫系统。以下是关键实现步骤:
import requests
import time
import random
from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}
def get_job_data(page):
base_url = "https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{}.html"
try:
response = requests.get(base_url.format(page), headers=headers)
response.raise_for_status()
return response.text
except Exception as e:
print(f"获取第{page}页数据失败: {e}")
return None
提示:在实际项目中,建议添加代理IP轮换和请求间隔控制,避免触发网站反爬机制。合理的请求间隔应设置在3-5秒之间。
1.2 数据解析与存储
获取原始数据后,我们需要从中提取结构化信息。招聘网站返回的数据通常是JSON格式,可以直接解析:
import json
import pandas as pd
from bs4 import BeautifulSoup
def parse_job_data(html):
soup = BeautifulSoup(html, 'html.parser')
script = soup.find('script', text=re.compile('window.__SEARCH_RESULT__'))
if not script:
return None
json_str = re.search(r'window.__SEARCH_RESULT__ = (.*?)</script>', str(script), re.DOTALL).group(1)
data = json.loads(json_str)
jobs = []
for item in data['engine_jds']:
job = {
'title': item.get('job_name'),
'company': item.get('company_name'),
'city': item.get('workarea_text'),
'salary': item.get('providesalary_text'),
'experience': item.get('attribute_text', [])[1] if len(item.get('attribute_text', [])) > 1 else None,
'education': item.get('attribute_text', [])[2] if len(item.get('attribute_text', [])) > 2 else None,
'company_type': item.get('companytype_text'),
'company_size': item.get('companysize_text'),
'publish_date': item.get('issuedate')
}
jobs.append(job)
return pd.DataFrame(jobs)
1.3 数据清洗关键步骤
原始招聘数据往往包含大量需要清洗的内容:
- 薪资标准化 :将"8千-1.5万/月"转换为可计算的数值范围
- 城市规范化 :处理"上海-浦东新区"这类区域信息
- 经验要求提取 :从混合字符串中分离工作年限要求
- 公司规模分类 :将描述性文字转换为规模等级
def clean_salary(salary_str):
if not salary_str or '面议' in salary_str:
return None, None
# 处理年薪和月薪的不同表达
if '万/年' in salary_str:
scale = 10000
period = '年'
elif '万/月' in salary_str:
scale = 10000
period = '月'
elif '千/月' in salary_str:
scale = 1000
period = '月'
else:
return None, None
nums = re.findall(r'(\d+\.?\d*)', salary_str)
if len(nums) >= 2:
lower = float(nums[0]) * scale
upper = float(nums[1]) * scale
if period == '年':
lower = lower / 12
upper = upper / 12
return lower, upper
elif len(nums) == 1:
val = float(nums[0]) * scale
if period == '年':
val = val / 12
return val, val
else:
return None, None
2. 数据分析核心维度
2.1 薪资分布全景分析
薪资是求职者最关注的指标之一。我们可以从多个角度分析Python岗位的薪资分布:
import matplotlib.pyplot as plt
import seaborn as sns
# 计算平均薪资
df['avg_salary'] = df[['salary_lower', 'salary_upper']].mean(axis=1)
plt.figure(figsize=(12, 6))
sns.boxplot(x='city', y='avg_salary', data=df)
plt.title('各城市Python岗位薪资分布对比')
plt.xticks(rotation=45)
plt.show()
通过分析,我们通常会发现几个关键现象:
- 城市差异 :一线城市薪资明显高于二三线城市
- 薪资区间 :大多数岗位集中在8-25k/月范围
- 异常值 :少数高薪岗位可达50k以上
2.2 热门技能需求分析
从职位描述中提取技术关键词,可以了解市场最需要的Python技能:
| 技能关键词 | 出现频率 | 平均薪资 |
|---|---|---|
| Django | 42% | 18.5k |
| Flask | 38% | 17.2k |
| 爬虫 | 35% | 16.8k |
| 数据分析 | 45% | 19.2k |
| 机器学习 | 28% | 22.5k |
| 自动化测试 | 25% | 15.6k |
注意:技能需求会随市场变化而快速调整,建议每季度更新一次数据分析
2.3 公司规模与薪资关系
不同规模企业提供的薪资水平和要求往往有显著差异:
# 公司规模分类映射
size_map = {
'少于50人': '小型',
'50-150人': '中小型',
'150-500人': '中型',
'500-1000人': '中大型',
'1000-5000人': '大型',
'5000-10000人': '超大型',
'10000人以上': '集团型'
}
df['company_size_cat'] = df['company_size'].map(size_map)
plt.figure(figsize=(10, 6))
sns.barplot(x='company_size_cat', y='avg_salary', data=df,
order=['小型', '中小型', '中型', '中大型', '大型', '超大型', '集团型'])
plt.title('不同规模企业Python岗位平均薪资对比')
plt.show()
分析结果通常显示:
- 中小型企业提供的薪资波动较大
- 大型企业薪资较为稳定但上限较低
- 某些超大型科技公司会提供极具竞争力的薪资
3. 高级分析技巧
3.1 薪资预测模型构建
基于收集的数据,我们可以建立简单的薪资预测模型:
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
# 数据预处理
df_model = df.dropna(subset=['avg_salary'])
le_city = LabelEncoder()
le_size = LabelEncoder()
df_model['city_encoded'] = le_city.fit_transform(df_model['city'])
df_model['size_encoded'] = le_size.fit_transform(df_model['company_size_cat'])
# 特征选择
features = ['city_encoded', 'size_encoded', 'experience_num']
X = df_model[features]
y = df_model['avg_salary']
# 训练测试集分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 模型训练
model = RandomForestRegressor(n_estimators=100)
model.fit(X_train, y_train)
# 评估
print("模型R2分数:", model.score(X_test, y_test))
3.2 职位聚类分析
使用无监督学习算法可以发现隐藏在职位中的模式:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
# 提取职位关键词
tfidf = TfidfVectorizer(max_features=100, stop_words=['python'])
title_matrix = tfidf.fit_transform(df['title'])
# 聚类分析
kmeans = KMeans(n_clusters=5)
df['cluster'] = kmeans.fit_predict(title_matrix)
# 分析聚类结果
for i in range(5):
cluster_titles = df[df['cluster'] == i]['title'].sample(5)
print(f"\n聚类{i}代表性职位:")
for title in cluster_titles:
print("-", title)
典型的聚类结果可能包括:
- Web开发方向(Django/Flask)
- 数据分析方向(Pandas/NumPy)
- 自动化测试方向
- 爬虫工程师
- AI/机器学习方向
4. 数据可视化与报告生成
4.1 交互式可视化仪表盘
使用Plotly创建交互式可视化:
import plotly.express as px
fig = px.scatter(df, x='experience_num', y='avg_salary', color='city',
hover_data=['title', 'company'],
title='工作经验与薪资关系(按城市)')
fig.show()
fig2 = px.treemap(df, path=['city', 'company_size_cat'], values='avg_salary',
color='avg_salary', hover_data=['company'],
title='薪资分布树状图(城市->公司规模)')
fig2.show()
4.2 自动化报告生成
将分析结果整理成专业报告:
from jinja2 import Template
report_template = """
# Python岗位市场分析报告
## 关键发现
- 平均薪资: {{ "%.2f"|format(avg_salary) }}k/月
- 最高薪资岗位: {{ top_job.title }} ({{ "%.2f"|format(top_job.avg_salary) }}k/月)
- 最热门技能: {{ top_skill }}
## 分城市薪资对比
{% for city in city_salaries %}
- {{ city.city }}: {{ "%.2f"|format(city.avg) }}k/月 ({{ city.count }}个岗位)
{% endfor %}
## 技能需求词云

"""
template = Template(report_template)
report = template.render(
avg_salary=df['avg_salary'].mean(),
top_job=df.loc[df['avg_salary'].idxmax()],
top_skill=skill_counts.index[0],
city_salaries=df.groupby('city')['avg_salary'].agg(['mean', 'count']).reset_index().to_dict('records'),
wordcloud_path='skills_wordcloud.png'
)
with open('python_job_report.md', 'w') as f:
f.write(report)
4.3 动态数据监控系统
对于长期跟踪,可以建立自动化数据管道:
# 每日数据更新脚本示例
#!/bin/bash
# 1. 运行爬虫获取最新数据
python scrape_jobs.py --pages 10 --output latest.csv
# 2. 数据清洗和分析
python analyze_jobs.py --input latest.csv --output analysis.json
# 3. 生成可视化
python visualize.py --input analysis.json --output dashboard.html
# 4. 发送邮件报告
python send_report.py --file dashboard.html
所有评论(0)