使用Python爬取招聘数据、数据处理与可视化

程序说明

通过爬取“51job”获取招聘信息(以计算机软件为例),根据所获取数据分析领域相关工作职位需求,并通过可视化的方式展示分析行业就业情况(例如平均月薪、工作地点等)。

数据爬取

使用requests库请求网页内容,使用BeautifulSoup4解析网页。

观察网页结构

首先在爬取网页前,使用浏览器“开发者工具”,观察网页结构。
观察网页结构
例如,使用下面语句查找标签为"t3"的"div"元素,其中内容即为工作地点,通过构建循环即可得到该页所有工作地点项。

i.find('span',class_='t3').get_text()

通过观察页面链接,爬取所有页面

查看第2页链接为:

https://search.51job.com/list/000000,000000,0000,01,9,99,%2B,2,2.html

第3页链接为:

https://search.51job.com/list/000000,000000,0000,01,9,99,%2B,2,3.html

仅改变了页面数字,因此可以构造如下模式,并使用循环,爬取所有页面:

url_pattern = "https://search.51job.com/list/000000,000000,0000,01,9,99,%2B,2,{}.html"
for i in range(1,2001):
    url = url_pattern.format(i)

爬虫程序完整代码

import time
import requests
from bs4 import BeautifulSoup
import os
import csv

#构建请求头
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'
}
url_pattern = "https://search.51job.com/list/000000,000000,0000,01,9,99,%2B,2,{}.html"

if not os.path.exists("intro_job.csv"):
    #创建存储csv文件存储数据
    file = open('intro_job.csv', "w", encoding="utf-8-sig",newline='')
    csv_head = csv.writer(file)
    #表头
    header = ['job','company','place','salary','date','detail_url']
    csv_head.writerow(header)
    file.close()
    
for i in range(1,2001):
    #增加时延防止反爬虫
    time.sleep(5)
    url = url_pattern.format(i)
    response = requests.get(url=url, headers=headers)
    
    #声明网页编码方式,需要根据具体网页响应情况
    response.encoding = 'gbk'
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')
    # 解析
    for i in soup.find_all(lambda tag: tag.name=='div' and tag.get('class')==['el'])[4:]:
        job = i.find('p',class_='t1').a['title']
        company = i.find('span',class_='t2').a['title']
        place = i.find('span',class_='t3').get_text()
        salary = i.find('span',class_='t4').get_text()
        date = i.find('span',class_='t5').get_text()
        detail_url = i.find('p',class_='t1').a['href']
        with open('intro_job.csv', 'a+', encoding='utf-8-sig') as f:
            f.write(job + ',' + company + ',' + place + ',' + salary + ',' + date +',' + detail_url + '\n')

爬取数据结果

展示部分爬取结果:
部分数据展示

数据预处理

数据预处理阶段主要为了去除不完整的数据,例如有些职务的薪资未明确标出,可以采用丢弃此条数据的方式,或者使用全局平均值之类的处理方法,这里采用直接丢弃的方法。

import pandas as pd
from matplotlib import pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
import math
import re

#读取数据
df = pd.read_csv('intro_job.csv', encoding='utf-8-sig',usecols=["job", "company", "place", "salary", "date"])
#将相应字段数据保存至列表中
job_array = df['job'].values
company_array = df['company'].values
place_array = df['place'].values
salary_array = df['salary'].values
date_array = df['date'].values

#去除无效含有无效字段的数据,同时也需要去除其他列表中对应位置的数据
bool_array = np.ones_like(salary_array,dtype=np.bool)
for i in range(len(salary_array)):
    if isinstance(salary_array[i],float):
        bool_array[i] = False
        
print(len(job_array))
print(sum(bool_array))
job_array = job_array[bool_array]
print(len(job_array))
company_array = company_array[bool_array]
place_array = place_array[bool_array]
salary_array = salary_array[bool_array]
date_array = date_array[bool_array]

数据分析及可视化

薪资字段,由于计量的时间单位和数量级不同,有些采用年薪而另一些采用月薪或日薪甚至时薪,同时有一些单位为万元,有些单位为千元,因此需要统一单位,这里采用“千/月”作为单位。
而且由于薪资并非一个具体的值,而是一个范围区间,这里假设,在此区间内满足平均分布,因此取最高值和最低值的平均数。

#将工作地点转换成市,如"上海-浦东" => "上海"
place_array_city = []
for place in place_array:
    if re.findall('-',place):
        place_array_city.append(place[:place.find('-')])
    else:
        place_array_city.append(place)

def calc_money(salary_tmp):
    if re.findall('千',salary_tmp):
        salary_tmp=salary_tmp[:salary_tmp.find('千')]
    elif re.findall('万',salary_tmp):
        salary_tmp=salary_tmp[:salary_tmp.find('万')]
    elif re.findall('元',salary_tmp):
        salary_tmp=salary_tmp[:salary_tmp.find('元')]
    if re.findall('-',salary_tmp):
        salary_tmp = salary_tmp.split('-')
        #print(salary_tmp)
        return (float(salary_tmp[0]) + float(salary_tmp[1])) / 2
    else:
        return float(salary_tmp)

def calc_total(salary_tmp):
    money = calc_money(salary_tmp)
    if salary_tmp[-1] == '千':
        money *= 1000
    elif salary_tmp[-1] == '万':
        money *= 10000
    return money

def calc_mean(salary):
    if re.findall('小时',salary):
        salary_tmp = salary[:-3]
    else:
        salary_tmp = salary[:-2]
    money = calc_total(salary_tmp)
    if re.findall('年',salary):
        money /= 12.0
    elif re.findall('天',salary):
        money *= 30
    elif re.findall('小时',salary):
        money = money * 8 * 20
    return money

#计算平均月薪
salary_array_mean = []
for salary in salary_array:
    money = calc_mean(salary)
    salary_array_mean.append(money)

#城市中岗位数目字典,如"上海":1300,表示上海有1300个相关岗位
city_dict = {}
#城市中岗位薪酬字典,如"上海":10000,表示上海计算机软件工作岗位总月薪为10000,除以对应城市岗位数即为该城市平均月薪
salary_dict = {}
for i in range(len(place_array_city)):
    if city_dict.get(place_array_city[i]):
        city_dict[place_array_city[i]]+=1
        salary_dict[place_array_city[i]] += salary_array_mean[i]
    else:
        city_dict[place_array_city[i]] = 1
        salary_dict[place_array_city[i]] = salary_array_mean[i]

全国计算机软件平均月薪和各市平均薪酬

为了更清晰,仅展示招聘岗位数量在前20的城市。

#全国计算机软件平均月薪
mean_salary = sum(salary_array_mean)/len(salary_array_mean)
#字典排序
d_order=sorted(city_dict.items(),key=lambda x:x[1],reverse=True)
#前岗位数量前20平均月薪列表
mean_top_20 = []
#前岗位数量前20列表
city_top_20 = []
for i in d_order[:20]:
    mean_top_20.append(salary_dict[i[0]]/i[1])
    city_top_20.append(i[0])
ax = plt.axes()
labels = ax.get_xticklabels()
plt.plot(city_top_20,mean_top_20,marker='o',label='各市平均月薪')
plt.plot([mean_salary]*20,'--',label='全国平均月薪')
plt.setp(labels,rotation=30.)
plt.legend()
plt.rcParams['font.sans-serif'] = ['SimSun']
plt.show()

各市平均薪酬
其他绘图方式类似不再展示源代码。
同样也可以统计计算机软件岗位平均月薪最高的20座城市,这个图很奇怪啊,我看了一下,全是同一个公司在全国各地开出来年薪50万+的工作,不知道什么情况,本来准备分析月薪最高的城市的各区情况,这一看还是算了,还是看一下上海吧。
月薪前20城市

上海各区计算机软件工作岗位数及平均薪酬

上海各区计算机软件工作岗位数,其中上海是指未限定区的工作地点,而非整个上海总计算机岗位数。
各区岗位数
上海各区计算机软件平均薪酬,这里上海仍是指未限定区的工作地点,而非整个上海总平均月薪。
上海各区平均月薪

使用词云展示工作地点情况

最后使用wordcloud库,绘制词云展示工作地点。

from os import path
from PIL import Image
import matplotlib.pyplot as plt
import jieba
from wordcloud import WordCloud, STOPWORDS
import pandas as pd
import matplotlib.ticker as ticker
import numpy as np
import math
import re

df = pd.read_csv('intro_job.csv', encoding='utf-8-sig',usecols=["job", "company", "place", "salary", "date"])

place_array = df['place'].values
place_list = ','.join(place_array)
with open('text.txt','a+') as f:
    f.writelines(place_list)

###当前文件路径
d = path.dirname(__file__)

# Read the whole text.
file = open(path.join(d, 'text.txt')).read()
##进行分词
#停用词,去除异地招聘的
stopwords = ["异地","异地招聘","招聘"]
text_split = jieba.cut(file)  # 未去掉停用词的分词结果   list类型

#去掉停用词的分词结果  list类型
text_split_no = []
for word in text_split:
    if word not in stopwords:
        text_split_no.append(word)
#print(text_split_no)

text =' '.join(text_split_no)
#背景图片
picture_mask = np.array(Image.open(path.join(d, "path.png")))
stopwords = set(STOPWORDS)
stopwords.add("said")
wc = WordCloud(  
    #设置字体,指定字体路径
    font_path=r'C:\Windows\Fonts\simsun.ttc',  
    background_color="white",   
    max_words=2000,   
    mask=picture_mask,  
    stopwords=stopwords)  
# 生成词云
wc.generate(text)

# 存储图片
wc.to_file(path.join(d, "result.jpg"))

生成词云

The end

由于所爬取网页架构方式的变化,对爬虫代码进行修改(更新版本).
Enjoying coding!

  • 79
    点赞
  • 770
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 44
    评论
Python爬虫是一种通过编写程序来获取互联网上的数据的技术。对于爬取招聘网站数据,可以使用Python中的一些第三方库如Scrapy或BeautifulSoup来实现。 首先,我们需要分析招聘网站的HTML结构,找到我们需要爬取数据所在的元素位置。然后,编写Python代码,使用相应的库来提取所需的数据。这些数据可以包括职位名称、公司名称、薪资水平等。 接下来,我们可以使用Tableau来进行数据可视化和交互。Tableau是一款功能强大的商业智能工具,可以帮助我们将数据变成易于理解和分析的可视化图表。可以通过将爬取到的数据导入Tableau,然后使用Tableau的图表、地图、仪表盘等功能来展示数据。 通过Tableau的交互大屏功能,我们可以实现对数据的实时展示和交互。例如,我们可以设置数据刷新时间,使得大屏能够显示最新的招聘信息。我们还可以添加筛选器和参数控制,使用户能够自由地根据需求进行数据过滤和分析。 最后,将Python爬取数据和Tableau可视化交互大屏的源码整合起来,就可以实现将招聘网站数据爬取并用Tableau进行可视化展示的功能。这个源码可以分为两部分,一部分是爬虫代码,负责数据爬取和处理;另一部分是Tableau代码,负责将数据导入Tableau并进行可视化展示。 综上所述,通过Python爬虫获取招聘网站数据,并使用Tableau进行可视化交互大屏展示,是一种非常有效的数据分析方法。这样可以将庞大的数据转化为直观、易懂的图表,方便用户进行数据的理解和决策。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盼小辉丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值