python爬虫:爬取拉勾网职位并分析
程序员文章站
2022-04-28 09:04:31
...
博客内容:爬取拉钩网上的数据并进行分析,参考代码链接为点击打开链接。
网页爬取部分:
import requests
import math
import pandas as pd
import time
def get_json(url,num):
'''''从网页获取JSON,使用POST请求,加上头部信息'''
#my_headers 是json的一个实例
my_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
'Host':'www.lagou.com',
'Referer':'https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=&fromSearch=true&suginput=',
# 'Referer':'https://www.lagou.com/jobs/list_%E5%88%9D%E4%B8%AD%E7%89%A9%E7%90%86%E8%80%81%E5%B8%88?labelWords=&fromSearch=true&suginput=',
'X-Anit-Forge-Code':'0',
'X-Anit-Forge-Token': 'None',
'X-Requested-With':'XMLHttpRequest'
}
my_data = {
'first': 'true',
'pn':num,
'kd':'数据分析'}
res = requests.post(url, headers = my_headers, data = my_data)
res.raise_for_status() #检查请求是否成功,有错就会报出,正常就只会输出none
res.encoding = 'utf-8'
# 得到包含职位信息的字典
page = res.json()
return page
def get_page_num(count):
'''''计算要抓取的页数'''
# 每页15个职位,向上取整
res = math.ceil(count/15)
# 拉勾网最多显示30页结果
if res > 30:
return 30
else:
return res
def get_page_info(jobs_list):
'''''对一个网页的职位信息进行解析,返回列表'''
page_info_list = []
for i in jobs_list:
job_info = []
job_info.append(i['companyFullName'])
job_info.append(i['companyShortName'])
job_info.append(i['companySize'])
job_info.append(i['financeStage'])
job_info.append(i['district'])
job_info.append(i['positionName'])
job_info.append(i['workYear'])
job_info.append(i['education'])
job_info.append(i['salary'])
job_info.append(i['positionAdvantage'])
page_info_list.append(job_info)
return page_info_list
def main():
url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false'
# url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false'
# 先设定页数为1,获取总的职位数
page_1 = get_json(url,1)
total_count = page_1['content']['positionResult']['totalCount'] #通过分析网页,找到返回网页中的totalCount
num = get_page_num(total_count) #调用函数,计算出总网页数
total_info = []
time.sleep(20) #这里为什么要停20秒?
print('职位总数:{},页数:{}'.format(total_count,num)) #这里是python中的语法
for n in range(1,3):
# 对每个网页读取JSON, 获取每页数据
page = get_json(url,n)
jobs_list = page['content']['positionResult']['result']
# print(jobs_list)
page_info = get_page_info(jobs_list)
total_info += page_info
# print(total_info)
print('已经抓取第{}页, 职位总数:{}'.format(n, len(total_info)))
# 每次抓取完成后,暂停一会,防止被服务器拉黑
time.sleep(30)
#将总数据转化为data frame再输出
df = pd.DataFrame(data = total_info,columns = ['公司全名','公司简称','公司规模','融资阶段','区域','职位名称','工作经验','学历要求','工资','职位福利'])
df.to_csv('lagou_datamini_jobs.csv',index = False)
print('已保存为csv文件.')
if __name__== "__main__":
main()
数据分析代码:
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from wordcloud import WordCloud
from scipy.misc import imread
import jieba
from pylab import mpl
# 使matplotlib模块能显示中文
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 读取数据
df = pd.read_csv('lagou_jobs.csv', encoding = 'gbk')
#df = pd.read_csv(r'H:\pycharm\python\reptileLagou\reptile\lagou_jobs.csv', encoding='gbk')
# 数据清洗,剔除实习岗位
#pandas删除某行的方式是先找到它的行索引
df.drop(df[df['职位名称'].str.contains('实习')].index, inplace=True)#找到需要剔除的关键字的位置后再进行剔除
# print(df.describe())
# 由于CSV文件内的数据是字符串形式,先用正则表达式将字符串转化为列表,再取区间的均值
pattern = '\d+'
df['工作年限'] = df['工作经验'].str.findall(pattern)
avg_work_year = []
for i in df['工作年限']:
# 如果工作经验为'不限'或'应届毕业生',那么匹配值为空,工作年限为0
if len(i) == 0:
avg_work_year.append(0)
# 如果匹配值为一个数值,那么返回该数值
elif len(i) == 1:
avg_work_year.append(int(''.join(i)))
# 如果匹配值为一个区间,那么取平均值
else:
num_list = [int(j) for j in i]
avg_year = sum(num_list)/2
avg_work_year.append(avg_year)
df['经验'] = avg_work_year
# 将字符串转化为列表,再取区间的前25%,比较贴近现实
df['salary'] = df['工资'].str.findall(pattern)
avg_salary = []
for k in df['salary']:
int_list = [int(n) for n in k]
avg_wage = int_list[0]+(int_list[1]-int_list[0])/4
avg_salary.append(avg_wage)
df['月工资'] = avg_salary
# 将清洗后的数据保存,以便检查
df.to_csv('draft.csv', index = False)
# 描述统计
print('数据分析师工资描述:\n{}'.format(df['月工资'].describe())) #pandas 的describe()函数会列出各列的和、平均数、方差、最小值、最大值以及quantile数值
# 绘制频率直方图并保存
plt.hist(df['月工资'],bins = 12)
plt.xlabel('工资 (千元)')
plt.ylabel('频数')
plt.title("工资直方图")
plt.savefig('histogram.jpg')
plt.show()
# 绘制饼图并保存
count = df['区域'].value_counts()
# 将龙华区和龙华新区的数据汇总
count['龙华新区'] += count['龙华区']
del count['龙华区']
plt.pie(count, labels = count.keys(),labeldistance=1.4,autopct='%2.1f%%')
plt.axis('equal') # 使饼图为正圆形
plt.legend(loc='upper left', bbox_to_anchor=(-0.1, 1))
plt.savefig('pie_chart.jpg')
plt.show()
# 绘制词云,将职位福利中的字符串汇总
text = ''
for line in df['职位福利']:
text += line
# 使用jieba模块将字符串分割为单词列表
cut_text = ' '.join(jieba.cut(text))
color_mask = imread('cloud.jpg') #设置背景图
cloud = WordCloud(
# font_path = 'yahei.ttf',
font_path='simhei.ttf',#字体格式,不设置就会乱码,如果加载的字体格式环境里不存在会报OSError的错。
background_color = 'white',#背景颜色
mask = color_mask,#词云背景图
max_words = 1000,#最大单词数
max_font_size = 100#最大字体号
)
word_cloud = cloud.generate(cut_text)#产生词云
# 保存词云图片
word_cloud.to_file('word_cloud.jpg')#保存词云
plt.imshow(word_cloud)#显示词云图片
plt.axis('off')
plt.show()
# 实证统计,将学历不限的职位要求认定为最低学历:大专
df['学历要求'] = df['学历要求'].replace('不限','大专')
# 学历分为大专\本科\硕士,将它们设定为虚拟变量
dummy_edu = pd.get_dummies(df['学历要求'],prefix = '学历')
# 构建回归数组
df_with_dummy = pd.concat([df['月工资'],df['经验'],dummy_edu],axis = 1)
# 建立多元回归模型
y = df_with_dummy['月工资']
X = df_with_dummy[['经验','学历_大专','学历_本科','学历_硕士']]
X=sm.add_constant(X)
model = sm.OLS(y,X)
results = model.fit()
print('回归方程的参数:\n{}\n'.format(results.params))
print('回归结果:\n{}'.format(results.summary()))
数据分析结果:
图一:工资频率直方图
图二:岗位位置分布图
图三:岗位福利待遇词云图
推荐阅读
-
网易云歌单信息爬取及数据分析(python爬虫)
-
Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码
-
python网络爬虫之解析网页的XPath(爬取Path职位信息)[三]
-
[python爬虫]爬取英雄联盟所有英雄数据并下载所有英雄皮肤
-
Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租
-
PYTHON爬虫大作业:豆瓣读书“小说”标签下1000本书籍的爬取与分析
-
荐 Python爬虫:基于Scrapy爬取京东商品数据并保存到mysql且下载商品图片
-
python3爬虫-通过selenium登陆拉钩,爬取职位信息
-
爬取拉勾网并进行数据分析
-
python爬虫 爬取验证码并识别