侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python如何爬取网站数据并进行数据可视化

Python  /  管理员 发布于 7年前   337

前言

爬取拉勾网关于python职位相关的数据信息,并将爬取的数据已csv各式存入文件,然后对csv文件相关字段的数据进行清洗,并对数据可视化展示,包括柱状图展示、直方图展示、词云展示等并根据可视化的数据做进一步的分析,其余分析和展示读者可自行发挥和扩展包括各种分析和不同的存储方式等。。。。。

一、爬取和分析相关依赖包

  • Python版本: Python3.6
  • requests: 下载网页
  • math: 向上取整
  • time: 暂停进程
  • pandas:数据分析并保存为csv文件
  • matplotlib:绘图
  • pyecharts:绘图
  • statsmodels:统计建模
  • wordcloud、scipy、jieba:生成中文词云
  • pylab:设置画图能显示中文

在以上安装或使用过程中可能读者会遇到安装或导入失败等问题自行百度,选择依赖包的合适版本

二、分析网页结构

通过Chrome搜索'python工程师',然后右键点击检查或者F12,,使用检查功能查看网页源代码,当我们点击下一页观察浏览器的搜索栏的url并没有改变,这是因为拉勾网做了反爬虫机制, 职位信息并不在源代码里,而是保存在JSON的文件里,因此我们直接下载JSON,并使用字典方法直接读取数据.即可拿到我们想要的python职位相关的信息,

待爬取的python工程师职位信息如下:

为了能爬到我们想要的数据,我们要用程序来模拟浏览器来查看网页,所以我们在爬取的过程中会加上头信息,头信息也是我们通过分析网页获取到的,通过网页分析我们知道该请求的头信息,以及请求的信息和请求的方式是POST请求,这样我们就可以该url请求拿到我们想的数据做进一步处理

爬取网页信息代码如下:

import requestsurl = ' https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'def get_json(url, num): """ 从指定的url中通过requests请求携带请求头和请求体获取网页中的信息, :return: """ url1 = 'https://www.lagou.com/jobs/list_python%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88?labelWords=&fromSearch=true&suginput=' 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=',  'X-Anit-Forge-Code': '0',  'X-Anit-Forge-Token': 'None',  'X-Requested-With': 'XMLHttpRequest' } data = {  'first': 'true',  'pn': num,  'kd': 'python工程师'} s = requests.Session() print('建立session:', s, '\n\n') s.get(url=url1, headers=headers, timeout=3) cookie = s.cookies print('获取cookie:', cookie, '\n\n') res = requests.post(url, headers=headers, data=data, cookies=cookie, timeout=3) res.raise_for_status() res.encoding = 'utf-8' page_data = res.json() print('请求响应结果:', page_data, '\n\n') return page_dataprint(get_json(url, 1))

通过搜索我们知道每页显示15个职位,最多显示30页,通过分析网页源代码知道,可以通过JSON里读取总职位数,通过总的职位数和每页能显示的职位数.我们可以计算出总共有多少页,然后使用循环按页爬取, 最后将职位信息汇总, 写入到CSV格式的文件中.

程序运行结果如图:

爬取所有python相关职位信息如下:

三、数据清洗后入库

数据清洗其实会占用很大一部分工作,我们在这里只做一些简单的数据分析后入库。在拉勾网输入python相关的职位会有18988个。你可以根据工作中需求选择要入库的字段,并对一些字段做进一步的筛选,比如我们可以去除职位名称中为实习生的岗位,过滤指定的字段区域在我们指定区域的职位,取字段薪资的平均值,以最低值和差值的四分之一为平均值等等根据需求自由发挥

import pandas as pdimport matplotlib.pyplot as pltimport statsmodels.api as smfrom wordcloud import WordCloudfrom scipy.misc import imreadfrom imageio import imreadimport jiebafrom pylab import mpl# 使用matplotlib能够显示中文mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题# 读取数据df = pd.read_csv('Python_development_engineer.csv', encoding='utf-8')# 进行数据清洗,过滤掉实习岗位# df.drop(df[df['职位名称'].str.contains('实习')].index, inplace=True)# print(df.describe())# 由于csv文件中的字符是字符串形式,先用正则表达式将字符串转化为列表,在去区间的均值pattern = '\d+'# print(df['工作经验'], '\n\n\n')# print(df['工作经验'].str.findall(pattern))df['工作年限'] = df['工作经验'].str.findall(pattern)print(type(df['工作年限']), '\n\n\n')avg_work_year = []count = 0for i in df['工作年限']: # print('每个职位对应的工作年限',i) # 如果工作经验为'不限'或'应届毕业生',那么匹配值为空,工作年限为0 if len(i) == 0:  avg_work_year.append(0)  # print('nihao')  count += 1 # 如果匹配值为一个数值,那么返回该数值 elif len(i) == 1:  # print('hello world')  avg_work_year.append(int(''.join(i)))  count += 1 # 如果匹配为一个区间则取平均值 else:  num_list = [int(j) for j in i]  avg_year = sum(num_list) / 2  avg_work_year.append(avg_year)  count += 1print(count)df['avg_work_year'] = avg_work_year# 将字符串转化为列表,薪资取最低值加上区间值得25%,比较贴近现实df['salary'] = df['薪资'].str.findall(pattern)#avg_salary_list = []for k in df['salary']: int_list = [int(n) for n in k] avg_salary = int_list[0] + (int_list[1] - int_list[0]) / 4 avg_salary_list.append(avg_salary)df['月薪'] = avg_salary_list# df.to_csv('python.csv', index=False)

四、数据可视化展示

下面是对数据的可视化展示,仅以部分视图进行一些可视化的展示,如果读者想对其他字段做一些展示以及想使用不同的视图类型进行展示,请自行发挥,注:以下代码中引入的模块见最后的完整代码

1、绘制python薪资的频率直方图并保存

如果我们想看看关于互联网行业python工程师相关的岗位大家普遍薪资的一个分部区间在哪个范围,占据了多达的比例我们就可以借助matplotlib库,来将我们保存在csv文件中的数据进行可视化的展示,然我们能够更直观的看到数据的一个分部趋势

# 绘制python薪资的频率直方图并保存plt.hist(df['月薪'],bins=8,facecolor='#ff6700',edgecolor='blue') # bins是默认的条形数目plt.xlabel('薪资(单位/千元)')plt.ylabel('频数/频率')plt.title('python薪资直方图')plt.savefig('python薪资分布.jpg')plt.show()

运行结果如下:

2、绘制python相关职位的地理位置饼状图

通过地理python职位地理位置的分部我们可以大致了解IT行业主要集中分部在哪些城市,这样也更利于我们选择地域进行选择性就业,可以获得更多的面试机会等,参数可自行调试,或根据需要添加。

# 绘制饼状图并保存city = df['城市'].value_counts()print(type(city))# print(len(city))label = city.keys()print(label)city_list = []count = 0n = 1distance = []for i in city: city_list.append(i) print('列表长度', len(city_list)) count += 1 if count > 5:  n += 0.1  distance.append(n) else:  distance.append(0)plt.pie(city_list, labels=label, labeldistance=1.2, autopct='%2.1f%%', pctdistance=0.6, shadow=True, explode=distance)plt.axis('equal') # 使饼图为正圆形plt.legend(loc='upper left', bbox_to_anchor=(-0.1, 1))plt.savefig('python地理位置分布图.jpg')plt.show()

运行结果如下:

3、绘制基于pyechart的城市分布柱状图

pycharts是python中调用百度基于js开发的echarts接口,也可以对数据进行各种可视化操作,更多数据可视化图形展示,可参考echarts官网:https://www.echartsjs.com/,echarts官网提供了各种实例供我们参考,如折线图、柱状图、饼图、路径图、树图等等,基于pyecharts的文档可参考以下官网:https://pyecharts.org/#/,更多用法也可自行百度网络资源

city = df['城市'].value_counts()print(type(city))print(city)# print(len(city))keys = city.index # 等价于keys = city.keys()values = city.valuesfrom pyecharts import Barbar = Bar("python职位的城市分布图")bar.add("城市", keys, values)bar.print_echarts_options() # 该行只为了打印配置项,方便调试时使用bar.render(path='a.html')

运行结果如下:

4、绘制python福利相关的词云

词云图又叫文字云,是对文本数据中出现频率较高的关键词予以视觉上的突出,形成"关键词的渲染"就类似云一样的彩色图片,从而过滤掉大量的文本信息,,使人一眼就可以领略文本数据的主要表达意思。利用jieba分词和词云生成WorldCloud(可自定义背景),下面就是对python相关职位的福利做了一个词云的展示,可以更直观的看到大多数公司的福利待遇集中在哪些地方

# 绘制福利待遇的词云text = ''for line in df['公司福利']: if len(eval(line)) == 0:  continue else:  for word in eval(line):   # print(word)   text += wordcut_word = ','.join(jieba.cut(text))word_background = imread('公主.jpg')cloud = WordCloud( font_path=r'C:\Windows\Fonts\simfang.ttf', background_color='black', mask=word_background, max_words=500, max_font_size=100, width=400, height=800)word_cloud = cloud.generate(cut_word)word_cloud.to_file('福利待遇词云.png')plt.imshow(word_cloud)plt.axis('off')plt.show()

运行结果如下:

五、爬虫及可视化完整代码

完整代码在下面,代码均测试可正常运行,感兴趣的小伙伴可去尝试和了解其中的使用方法,如运行或者模块安装等失败可以在评论区进行留言,让我们一同解决吧

如果你觉得对你有帮助可以点个赞哦,原创内容转载需说明出处!!!

1、爬虫完整代码

为了防止我们频繁请求一个网站被限制ip,我们在爬取每一页后选择睡一段时间,当然你也可以使用代理等其他方式自行实现

import requestsimport mathimport timeimport pandas as pddef get_json(url, num): """ 从指定的url中通过requests请求携带请求头和请求体获取网页中的信息, :return: """ url1 = 'https://www.lagou.com/jobs/list_python%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88?labelWords=&fromSearch=true&suginput=' 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=',  'X-Anit-Forge-Code': '0',  'X-Anit-Forge-Token': 'None',  'X-Requested-With': 'XMLHttpRequest' } data = {  'first': 'true',  'pn': num,  'kd': 'python工程师'} s = requests.Session() print('建立session:', s, '\n\n') s.get(url=url1, headers=headers, timeout=3) cookie = s.cookies print('获取cookie:', cookie, '\n\n') res = requests.post(url, headers=headers, data=data, cookies=cookie, timeout=3) res.raise_for_status() res.encoding = 'utf-8' page_data = res.json() print('请求响应结果:', page_data, '\n\n') return page_datadef get_page_num(count): """ 计算要抓取的页数,通过在拉勾网输入关键字信息,可以发现最多显示30页信息,每页最多显示15个职位信息 :return: """ page_num = math.ceil(count / 15) if page_num > 30:  return 30 else:  return page_numdef get_page_info(jobs_list): """ 获取职位 :param jobs_list: :return: """ 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'])  job_info.append(i['industryField'])  job_info.append(i['firstType'])  job_info.append(i['companyLabelList'])  job_info.append(i['secondType'])  job_info.append(i['city'])  page_info_list.append(job_info) return page_info_listdef main(): url = ' https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false' first_page = get_json(url, 1) total_page_count = first_page['content']['positionResult']['totalCount'] num = get_page_num(total_page_count) total_info = [] time.sleep(10) print("python开发相关职位总数:{},总页数为:{}".format(total_page_count, num)) for num in range(1, num + 1):  # 获取每一页的职位相关的信息  page_data = get_json(url, num) # 获取响应json  jobs_list = page_data['content']['positionResult']['result'] # 获取每页的所有python相关的职位信息  page_info = get_page_info(jobs_list)  print("每一页python相关的职位信息:%s" % page_info, '\n\n')  total_info += page_info  print('已经爬取到第{}页,职位总数为{}'.format(num, len(total_info)))  time.sleep(20)  # 将总数据转化为data frame再输出,然后在写入到csv各式的文件中  df = pd.DataFrame(data=total_info,       columns=['公司全名', '公司简称', '公司规模', '融资阶段', '区域', '职位名称', '工作经验', '学历要求', '薪资', '职位福利', '经营范围',         '职位类型', '公司福利', '第二职位类型', '城市'])  # df.to_csv('Python_development_engineer.csv', index=False)  print('python相关职位信息已保存')if __name__ == '__main__': main()

2、可视化完整代码

数据可视化涉及到matplotlib、jieba、wordcloud、pyecharts、pylab、scipy等等模块的使用,读者可以自行了解各个模块的使用方法,和其中涉及的各种参数

import pandas as pdimport matplotlib.pyplot as pltimport statsmodels.api as smfrom wordcloud import WordCloudfrom scipy.misc import imread# from imageio import imreadimport jiebafrom pylab import mpl# 使用matplotlib能够显示中文mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题# 读取数据df = pd.read_csv('Python_development_engineer.csv', encoding='utf-8')# 进行数据清洗,过滤掉实习岗位# df.drop(df[df['职位名称'].str.contains('实习')].index, inplace=True)# print(df.describe())# 由于csv文件中的字符是字符串形式,先用正则表达式将字符串转化为列表,在去区间的均值pattern = '\d+'# print(df['工作经验'], '\n\n\n')# print(df['工作经验'].str.findall(pattern))df['工作年限'] = df['工作经验'].str.findall(pattern)print(type(df['工作年限']), '\n\n\n')avg_work_year = []count = 0for i in df['工作年限']: # print('每个职位对应的工作年限',i) # 如果工作经验为'不限'或'应届毕业生',那么匹配值为空,工作年限为0 if len(i) == 0:  avg_work_year.append(0)  # print('nihao')  count += 1 # 如果匹配值为一个数值,那么返回该数值 elif len(i) == 1:  # print('hello world')  avg_work_year.append(int(''.join(i)))  count += 1 # 如果匹配为一个区间则取平均值 else:  num_list = [int(j) for j in i]  avg_year = sum(num_list) / 2  avg_work_year.append(avg_year)  count += 1print(count)df['avg_work_year'] = avg_work_year# 将字符串转化为列表,薪资取最低值加上区间值得25%,比较贴近现实df['salary'] = df['薪资'].str.findall(pattern)#avg_salary_list = []for k in df['salary']: int_list = [int(n) for n in k] avg_salary = int_list[0] + (int_list[1] - int_list[0]) / 4 avg_salary_list.append(avg_salary)df['月薪'] = avg_salary_list# df.to_csv('python.csv', index=False)"""1、绘制python薪资的频率直方图并保存"""plt.hist(df['月薪'], bins=8, facecolor='#ff6700', edgecolor='blue') # bins是默认的条形数目plt.xlabel('薪资(单位/千元)')plt.ylabel('频数/频率')plt.title('python薪资直方图')plt.savefig('python薪资分布.jpg')plt.show()"""2、绘制饼状图并保存"""city = df['城市'].value_counts()print(type(city))# print(len(city))label = city.keys()print(label)city_list = []count = 0n = 1distance = []for i in city: city_list.append(i) print('列表长度', len(city_list)) count += 1 if count > 5:  n += 0.1  distance.append(n) else:  distance.append(0)plt.pie(city_list, labels=label, labeldistance=1.2, autopct='%2.1f%%', pctdistance=0.6, shadow=True, explode=distance)plt.axis('equal') # 使饼图为正圆形plt.legend(loc='upper left', bbox_to_anchor=(-0.1, 1))plt.savefig('python地理位置分布图.jpg')plt.show()"""3、绘制福利待遇的词云"""text = ''for line in df['公司福利']: if len(eval(line)) == 0:  continue else:  for word in eval(line):   # print(word)   text += wordcut_word = ','.join(jieba.cut(text))word_background = imread('公主.jpg')cloud = WordCloud( font_path=r'C:\Windows\Fonts\simfang.ttf', background_color='black', mask=word_background, max_words=500, max_font_size=100, width=400, height=800)word_cloud = cloud.generate(cut_word)word_cloud.to_file('福利待遇词云.png')plt.imshow(word_cloud)plt.axis('off')plt.show()"""4、基于pyechart的柱状图"""city = df['城市'].value_counts()print(type(city))print(city)# print(len(city))keys = city.index # 等价于keys = city.keys()values = city.valuesfrom pyecharts import Barbar = Bar("python职位的城市分布图")bar.add("城市", keys, values)bar.print_echarts_options() # 该行只为了打印配置项,方便调试时使用bar.render(path='a.html')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    Python3实现汉语转换为汉语拼音
    下一条:
    Python画图实现同一结点多个柱状图的示例
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客