基于python的招聘信息可视化

一、设计方案(不少于1200字)

1.1 课题概述

对课题的基本信息进行简要说明。

本课程设计的课题为“招聘信息可视化”,实现的功能为对特定职业的招聘信息进行采集、预处理和可视化展示。

选定“月嫂”为例,利用爬虫技术从多家招聘平台中获取相关信息,并经过数据预处理,数据清洗和统计分析的流程,将结果以柱状图、词云等形式可视化呈现,便于用户直观地了解“月嫂”的价格分布、城市分布、学历要求,经验要求等。

1.2 详细设计

1.2.1 总体方案

对课题的设计原则、运行流程、模块划分等进行说明。模块数量根据设计方案的实际情况进行增减。

本课程设计的总体方案分为以下步骤:

步骤一:爬取招聘信息。使用爬虫技术,从BOSS直聘、前程无忧、智联招聘等多家招聘平台中获取“月嫂”相关招聘信息。

步骤二:数据预处理。对采集到的原始数据进行清洗、去重、剔除虚假信息,对数据进行统一格式等操作,确保数据质量。

步骤三:统计分析。对经过清洗处理后的数据进行统计分析,价格分布、城市分布、学历要求,经验要求,以便从中提取有用的信息。

步骤四:可视化展示。以柱状图、折线图等形式,将统计分析后的数据可视化展示,让用户更加直观地了解“月嫂”相关信息,并且对“月嫂”职业进行深入分析。

1.2.2 模块1

爬取招聘信息

本模块通过爬虫技术,从多个招聘网站上爬取“月嫂”相关的招聘信息。具体实现的流程如下:

首先,需要分析和了解目标网站的页面结构和数据格式,确定需要采集的数据内容和数据存储方式。

然后,利用Python等编程语言编写爬虫程序,根据分析的内容,访问目标网站,并通过分析页面结构和数据格式,确定需要采集数据的xpath或CSS选择器等元素。

先对难度较低的智联招聘和前程无忧网站进行爬取,爬完后发现数据量太少,之后向BOSS直聘进行爬取,使用谷歌浏览器的自动点击脚本,实现搜索,选择地区等操作,由于BOSS只显示出10页数据,所以需要选择更小的范围,所以在爬取时耗费了较多时间。

最后,将采集到的数据存储到本地文件中,并将几个网站的数据合并,以备后续的数据预处理和统计分析使用。

1.2.3 模块2

数据预处理

本模块通过对采集到的招聘信息进行清洗、去重、剔除虚假信息等操作,确保获取的数据质量。

具体实现的流程如下:

首先,需要对数据进行去重处理,将每一列都一样的数据进行删除,以避免重复数据的影响。

然后,需要对数据进行薪资的格式统一化,使用正则表达式将列如8-10k,5千-1万等数据统一化为“5000-6000元/月”的形式。

最后,将少量不符合形式的数据进行删除,并且把每个地区的城市名提取出来,还有把薪资计算平均数提取出来,以便后续进行分析与可视化处理。

1.2.3 模块3

统计分析和可视化展示

本模块将经过预处理的数据进行统计分析,并以柱状图、词云等形式进行可视化展示,从而让用户更加直观地了解“月嫂”相关信息,具体实现的流程如下:

首先,通过数据分析,获取“月嫂”在不同城市和不同学历。不同经验的需求量和工资的高低。将图像与城市GDP对比进行分析,发现在GDP高的城市中对职位的需求量也较高,并且工资也更高。

然后,结合工资分布,将数据可视化展示,以柱状图、折线图等形式呈现价格变化趋势和不同,并且对图形进行更加深入的分析。

二、总结(不少于800字)

对课题的执行情况进行详细说明,包括但不限于已取得的经验、教训,以及今后努力的方向等等。

本次课程设计以“招聘信息可视化”为主题,对特定职业“月嫂”的相关信息进行数据采集、处理和展示。在实现过程中,我们经历了以下步骤:

1. 确定课题和技术要求。

2. 分析招聘网站,确定数据采集方式。

3. 编写爬虫程序,爬取相关招聘信息。

4. 对采集到的数据进行格式化和清洗处理。

5. 对处理后的数据进行了可视化展示,对图形进行深入的数据分析。

在完成课程设计过程中,收获了很多效益和体会:

首先,我们学习到了很多有关数据采集、数据处理和数据可视化的知识,加强了我们对这一方面的了解和实践能力。

其次,我们了解到了爬虫程序的运行原理和应用场景,掌握了Python编程技术,深入理解了XPath、CSS 选择器等爬虫技术的运用方式。

但是,我们也遇到了许多问题和挑战。其中最主要的问题是难以保证数据的准确性和全面性。我们通过反复清洗数据来尽可能保证数据质量,但是依旧有些数据仍无法得到完美的清洗,所以之后我直接将不符合格式的少量数据进行了删除。此外,计算机性能对程序的速度和效率都有很大影响,可以采取多线程来跑两个爬虫代码以此加快爬取速度。我们需要更加深入地学习计算机原理和编程技术。

从以上的经验和教训中,我们发现需要在以下方面加以改进:

1. 提高数据质量。除了清洗数据之外,我们还要强化对数据的验证和审核,最大程度地保证数据的准确性和全面性。

2. 加强计算机基础知识的学习。通过学习机器学习、算法设计与分析、操作系统等课程,进一步理解和熟练掌握计算机原理和技术。

3. 拓展应用场景。不仅局限于对招聘信息的采集和分析,还可以将所学知识应用到更广泛的领域中,如商业数据分析、社交媒体数据挖掘等。

总之,本次课程设计给我们提供了实践机会,让我们理解到数据采集、处理和可视化的重要性,掌握了许多实用技能。在今后的学习和工作中,我们将不断提高自身技能和能力,不断创新、勇于尝试,不断追求更高质量和更好的效果,最终取得更大的成功和成就。

部分代码

爬虫代码:

BOSS招聘:

import csv
import random
import time
from lxml import etree
from selenium import webdriver
# 实现规避检测
from selenium.webdriver import ChromeOptions
# 实现无可视化界面的
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By


from selenium.webdriver import Edge
# 实现规避检测
from selenium.webdriver import EdgeOptions

# 去除浏览器识别,去除Edge正在受到自动检测软件的控制
# edge_options = EdgeOptions()
# edge_options.add_experimental_option('excludeSwitches', ['enable-automation'])
# edge_options.add_experimental_option('detach', True)
# edge_options.add_argument("'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'")
# 设置代理,如果需要的话
# edge_options.add_argument("--proxy-server=http://ip:port")

# web = Edge( options=edge_options)

chrome_options = ChromeOptions()
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_experimental_option('detach', True)
chrome_options.add_argument("--disable-blink-features=AutomationControlled")

options = Options()
options.add_argument('--headless')  # 设置为无头
options.add_argument('--disable-gpu')  # 设置没有使用gpu
options.add_argument(
    'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')


# 实例化一个浏览器对象(传入浏览器的驱动程序)
web = webdriver.Chrome(chrome_options=chrome_options, options=options)
# cookie_dict = {
#     'name': 'YD00951578218230%3AWM_NIKE',
#     'value': '9ca17ae2e6ffcda170e2e6eea4ea59b6ad8d94e83bb1a88fa7c45f879e8f82d46195b1a294cf59a593aebbae2af0fea7c3b92a819bba97d442b2b88995c279838b8db5e125a6868ad3f259b48bbaa9e1449b8ffd96f564f399a68db180a39afeb7f04386b88797db6386a6008cdc4fb2eaaf94b86b82f1bad9c679a5ba8b8aef6fac8aacacf17083ad99d2c63da5edb785b752a9b3bad3d7549bada2a8c768869f8aa4f425bbefbfb9cf59f1b089adb121f4989d8ce237e2a3',
#     'domain': 'www.zhipin.com'
# }
# web.add_cookie(cookie_dict)
with open('./stealth.min.js') as f:
    js = f.read()
web.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": js
})

s_time = time.time()

# # 利用xpath和css选择器提取数据
f = open('112.csv', mode='a', encoding='utf-8', newline='')
csv_write = csv.DictWriter(f, fieldnames=[
    '岗位名称',
    '工作地点',
    '薪资',
    '公司名称',
    '学历要求',
    '经验要求',
    # '发布日期',
])
# with open('cookies1.txt', 'r') as f:
#     cookie_str = f.read()
# cookies = eval(cookie_str)
# csv_write.writeheader()  # 写入表头

# web.get("https://www.zhipin.com")
#
# for name, value in cookies.items():
#     cookie_dict = {'name': name, 'value': value}
#     web.add_cookie(cookie_dict)
web.execute_cdp_cmd('Network.setExtraHTTPHeaders', {'headers': {'Referer': 'https://www.baidu.com'}})
time.sleep(1)


for page in range(1, 10):
    print(f'==============正在爬取{page}页信息==================')
    url = "https://www.zhipin.com/web/geek/job?query=%E6%9C%88%E5%AB%82&city=101240100&page={}".format(page)
    web.get(url)
    time.sleep(13)
    if page==1:
        jobData = web.find_elements(By.XPATH,'//*[@id="wrap"]/div[2]/div[2]/div/div[1]/div[2]/ul/li')
    else:
        jobData = web.find_elements(By.XPATH,'//*[@id="wrap"]/div[2]/div[2]/div/div[1]/div[1]/ul/li')


    # print(jobData)
    time.sleep(3)
    # 详情页面工作职责和任职资格划分

    for job in jobData:
        jobName = job.find_element(By.CLASS_NAME, 'job-name').text  # 职位名称
        time.sleep(0.5)
        jobSalary = job.find_element(By.CLASS_NAME, 'salary').text  # 工作薪资
        time.sleep(0.5)
        jobCompany = job.find_element(By.CLASS_NAME, 'company-name').text  # 公司名称
        time.sleep(0.5)
        address = job.find_element(By.CLASS_NAME, 'job-area').text  # 地点
        time.sleep(0.5)
        xueli = job.find_element(By.CLASS_NAME, 'tag-list').text[:4]  # 学历
        time.sleep(0.5)
        jingyan = job.find_element(By.CLASS_NAME, 'tag-list').text[-4:]  # 经验
        time.sleep(0.5)
        dit = {
            "岗位名称": jobName,
            "工作地点": address,
            "薪资": jobSalary,
            "公司名称": jobCompany,
            "学历要求": xueli,
            "经验要求": jingyan,

        }
        print(jobName, address, jobSalary, jobCompany,xueli,jingyan)
        csv_write.writerow(dit)
        time.sleep(3)
e_time = time.time()
print('用时:%f秒' % (e_time - s_time))
web.quit()

注意这里使用的是脚本进行模拟点击页面进行数据爬取,速度较慢但是比较稳定,使用前注意做好前期浏览器配置等工作。

前程无忧:

import csv
import random
import time
from lxml import etree
from selenium import webdriver
# 实现规避检测
from selenium.webdriver import ChromeOptions
# 实现无可视化界面的
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

# 去除浏览器识别,去除Chrome正在受到自动检测软件的控制
chrome_options = ChromeOptions()
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_experimental_option('detach', True)
chrome_options.add_argument("--disable-blink-features=AutomationControlled")

options = Options()
options.add_argument('--headless')  # 设置为无头
options.add_argument('--disable-gpu')  # 设置没有使用gpu
options.add_argument(
    'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')

# 实例化一个浏览器对象(传入浏览器的驱动程序)
web = webdriver.Chrome(chrome_options=chrome_options, options=options)
with open('./stealth.min.js') as f:
    js = f.read()
web.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": js
})




# 利用xpath和css选择器提取数据
f = open('11.csv', mode='a', encoding='utf-8', newline='')
csv_write = csv.DictWriter(f, fieldnames=[
    '岗位名称',
    '工作地点',
    '薪资',
    '公司名称',
    '工作经验',
    '学历要求',
    '发布日期',
])
csv_write.writeheader()  # 写入表头

# 找到职位框,输入搜索的内容
job_names = ['月嫂']
for j in job_names:
    # 定位输入框并查找相关职位
    # 发起请求
    web.get("https://www.51job.com/")
    time.sleep(3)  # 防止加载缓慢,休眠2秒
    web.find_element(By.XPATH, '//*[@id="kwdselectid"]').click()
    web.find_element(By.XPATH, '//*[@id="kwdselectid"]').clear()
    # 输入招聘岗位名称
    web.find_element(By.XPATH, '//*[@id="kwdselectid"]').send_keys(j)
    web.find_element(By.XPATH, '/html/body/div[3]/div/div[1]/div/button').click()  # 点击搜索
    # #切换城市
    time.sleep(3)
    web.find_element(By.XPATH, '//*[@id="app"]/div/div[2]/div/div/div[1]/div[2]/div[1]/div[1]/div[2]/div[2]').click()
    time.sleep(3)
    # web.find_element(By.XPATH, '//*[@id="pane-0"]/div/div/div[1]/span').click()
    # time.sleep(1)
    web.find_element(By.XPATH, '//*[@id="tab-10"]/div/div[2]').click()
    time.sleep(0.4)
    web.find_element(By.XPATH, '//*[@id="pane-10"]/div/div/div[2]/div[17]/span').click()
    time.sleep(0.4)
    web.find_element(By.XPATH, '//*[@id="pane-10"]/div/div/div[2]/div[18]/span').click()
    time.sleep(0.4)
    web.find_element(By.XPATH, '//*[@id="pane-10"]/div/div/div[2]/div[19]/span').click()
    time.sleep(0.4)
    web.find_element(By.XPATH, '//*[@id="pane-10"]/div/div/div[2]/div[20]/span').click()
    time.sleep(0.4)
    web.find_element(By.XPATH, '//*[@id="pane-10"]/div/div/div[2]/div[21]/span').click()
    # time.sleep(1)
    # web.find_element(By.XPATH, '//*[@id="pane-0"]/div/div/div[5]/span').click()
    time.sleep(1)
    web.find_element(By.XPATH, '//*[@id="dilog"]/div/div[3]/span/button').click()
    time.sleep(3)
    for page in range(1, 10):
        print(f'==============正在爬取{page}页信息==================')
        time.sleep(5)
        web.find_element(By.XPATH, '//*[@id="jump_page"]').click()
        time.sleep(random.randint(10, 30) * 0.1)
        web.find_element(By.XPATH, '//*[@id="jump_page"]').clear()
        time.sleep(random.randint(10, 40) * 0.1)
        web.find_element(By.XPATH, '//*[@id="jump_page"]').send_keys(page)
        time.sleep(random.randint(10, 30) * 0.1)
        web.find_element(By.XPATH,
                         '//*[@id="app"]/div/div[2]/div/div/div[2]/div/div[2]/div/div[3]/div/div/span[3]').click()

        # 定位招聘页面所有招聘公司
        time.sleep(3)
        jobData = web.find_elements(By.XPATH,
                                    '//*[@id="app"]/div/div[2]/div/div/div[2]/div/div[2]/div/div[2]/div[1]/div')

        # print(jobData)

        # 详情页面工作职责和任职资格划分

        for job in jobData:
            jobName = job.find_element(By.CLASS_NAME, 'jname.at').text  # 职位名称
            time.sleep(random.randint(5, 15) * 0.1)
            jobSalary = job.find_element(By.CLASS_NAME, 'sal').text  # 工作薪资
            time.sleep(random.randint(5, 15) * 0.1)
            jobCompany = job.find_element(By.CLASS_NAME, 'cname.at').text  # 公司名称
            time.sleep(random.randint(5, 15) * 0.1)
            # company_type_size = job.find_element(By.CLASS_NAME, 'dc.at').text  # 公司规模
            # time.sleep(random.randint(5, 15) * 0.1)
            # company_status = job.find_element(By.CLASS_NAME, 'int.at').text  # 所属行业
            # time.sleep(random.randint(5, 15) * 0.1)
            address_experience_education = job.find_element(By.CLASS_NAME, 'd.at').text  # 地点_经验_学历
            print(address_experience_education)
            length = len(address_experience_education.split('|'))
            if length == 3:
                address = address_experience_education.split('|')[0]  # 工作地点
                experience = address_experience_education.split('|')[1]  # 工作经验
                edu = address_experience_education.split('|')[2]  # 学历要求
            else:
                address = address_experience_education.split('|')[0]  # 工作地点
                experience = '无需经验'
                edu = '学历不限'
            time.sleep(random.randint(5, 15) * 0.1)
            update_date = job.find_element(By.CLASS_NAME, 'time').text  # 发布日期
            time.sleep(random.randint(5, 15) * 0.1)
            dit = {
                "岗位名称": jobName,
                "工作地点": address,
                "薪资": jobSalary,
                "公司名称": jobCompany,
                "工作经验": experience,
                "学历要求": edu,
                # "关键词": job_welf,
                "发布日期": update_date,
            }
            # print(f'正在爬取{jobCompany}公司')
            print(jobName,address, jobSalary, jobCompany, update_date,experience,edu)
            csv_write.writerow(dit)
            time.sleep(5)

 招聘需求最多的前十个城市的平均工资排行:

import pandas as pd
import seaborn as sns
import matplotlib as mpl
#配置之后便可使用
mpl.rcParams['font.family']='SimHei'
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False     # 正常显示负号
#可使用该例子查看效果
from matplotlib import pyplot as plt

# 读取数据集
data = pd.read_csv('66.csv', encoding='utf-8')

# 找到出现次数最多的十个城市
top_cities = data['城市'].value_counts()[:10].index.tolist()

# 将列表转换为DataFrame对象
top_cities_df = pd.DataFrame({'城市': top_cities})

# 合并这些城市的数据,并计算它们的平均工资
city_mean = pd.merge(data[data['城市'].isin(top_cities)], top_cities_df, on='城市').groupby(by="城市")["工资"].mean().round(2).reset_index()

# 按工资大小对城市平均工资进行排序
city_mean = city_mean.sort_values('工资', ascending=False)

# 绘制出现次数最多的十个城市的平均工资柱状图
plt.figure(figsize=(8,6))
ax = sns.barplot(x='城市', y='工资', data=city_mean)
plt.xticks(rotation=45)
plt.title('出现次数最多的十个城市的平均工资')
# 在每一列工资上显示数值
for p in ax.patches:
    ax.annotate("%.2f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()), ha='center', va='center', fontsize=10, color='gray', xytext=(0, 8), textcoords='offset points')
plt.show()

部分效果截图:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值