ToB企服应用市场:ToB评测及商务社交产业平台

标题: Python采集招聘数据信息(+详情页)并实现可视化 [打印本页]

作者: 风雨同行    时间: 2022-8-21 12:42
标题: Python采集招聘数据信息(+详情页)并实现可视化
本篇代码提供者: 青灯教育-自游老师

[环境使用]:

[模块使用]:

如果安装python第三方模块:

如何配置pycharm里面的python解释器?

pycharm如何安装插件?

基本流程思路:

一. 数据来源分析

网页开发者工具进行抓包分析....
二. 代码实现过程:

代码

导入模块
  1. # 导入数据请求模块
  2. import requests
  3. # 导入正则表达式模块
  4. import re
  5. # 导入json模块
  6. import json
  7. # 导入格式化输出模块
  8. import pprint
  9. # 导入csv模块
  10. import csv
  11. # 导入时间模块
  12. import time
  13. # 导入随机模块
  14. import random
  15. # 有没有用utf-8保存表格数据,乱码的?
  16. f = open('data多页_1.csv', mode='a', encoding='utf-8', newline='')  # 打开一个文件 data.csv
  17. csv_writer = csv.DictWriter(f, fieldnames=[
  18.     '职位',
  19.     '城市',
  20.     '经验',
  21.     '学历',
  22.     '薪资',
  23.     '公司',
  24.     '福利待遇',
  25.     '公司领域',
  26.     '公司规模',
  27.     '公司类型',
  28.     '发布日期',
  29.     '职位详情页',
  30.     '公司详情页',
  31. ])
  32. csv_writer.writeheader()
复制代码
 
1. 发送请求,

用python代码模拟浏览器对于url地址发送请求
不要企图一节课, 掌握所有内容, 要学习听懂思路, 每一步我们为什么这么做...
知道headers 1
不知道headers 2
headers 请求头, 作用伪装python代码, 伪装成浏览器
字典形式, 构建完整键值对
如果当你headers伪装不够的时候, 你可能会被服务器识别出来, 你是爬虫程序, 从而不给你相应的数据内容
  1. for page in range(1, 15):
  2.     print(f'正在采集第{page}页的数据内容')
  3.     time.sleep(random.randint(1, 2))
  4.     url = f'https://search.51job.com/list/010000%252C020000%252C030200%252C040000%252C090200,000000,0000,00,9,99,python,2,{page}.html'
  5.     headers = {
  6.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
  7.     }
  8.     response = requests.get(url=url, headers=headers)
  9.     print(response)  # <Response [200]> 响应对象<br>
复制代码
 
2. 获取数据

得到数据, 不是你想要数据内容, 你可能是被反爬了, 要多加一些伪装
  1. # print(response.text)  字符串数据类型
复制代码
 
3. 解析数据, 提取我们想要数据内容

re.findall() 就是从什么地方去找什么样数据内容
[0] 表示提取列表里面第一个元素 ---> list index out of range 所以你的列表是空列表
用正则表达式/css/xpath提取数据返回是空列表 ---> 1. 你语法写错 2. response.text 没有你想要数据
---> 是不是被反爬(验证码 需要登陆) 是不是headers参数给少了 是不是被封IP
  1.     html_data = re.findall('window.__SEARCH_RESULT__ = (.*?)</script>', response.text)[0]
  2.     # print(html_data)
  3.     json_data = json.loads(html_data)
  4.     # pprint.pprint(json_data)
  5.     # 通过字典取值方法 把职位信息列表提取出来, 通过for循环遍历一个一个提取职位信息
  6.     for index in json_data['engine_jds']:
  7.         # 根据冒号左边的内容, 提取冒号右边的内容
  8.         # pprint.pprint(index)
  9.         try:
  10.             dit = {
  11.                 '职位': index['job_title'],
  12.                 '城市': index['attribute_text'][0],
  13.                 '经验': index['attribute_text'][1],
  14.                 '学历': index['attribute_text'][2],
  15.                 '薪资': index['providesalary_text'],
  16.                 '公司': index['company_name'],
  17.                 '福利待遇': index['jobwelf'],
  18.                 '公司领域': index['companyind_text'],
  19.                 '公司规模': index['companysize_text'],
  20.                 '公司类型': index['companytype_text'],
  21.                 '发布日期': index['issuedate'],
  22.                 '职位详情页': index['job_href'],
  23.                 '公司详情页': index['company_href'],
  24.             }
  25.             csv_writer.writerow(dit)
  26.             print(dit)
  27.         except:
  28.             pass
复制代码
 
详情页数据

----> 爬虫基本思路是什么?
数据来源分析
请求响应 请求那个网站呢? 网址是什么 请求方式是什么 请求参数要什么?
发送请求 ---> 获取数据 ---> 解析数据 ---> 保存数据
导入模块
  1. import requests
  2. import parsel
  3. url = 'https://jobs.51job.com/shanghai-jdq/137393082.html?s=sou_sou_soulb&t=0_0'
  4. headers = {
  5.     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36',
  6. }
  7. response = requests.get(url=url, headers=headers)
  8. response.encoding = response.apparent_encoding  # 自动识别编码
  9. print(response.text)
  10. selector = parsel.Selector(response.text)
  11. content_1 = selector.css('.cn').get()
  12. content_2 = selector.css('.tCompany_main').get()
  13. content = content_1 + content_2
  14. # 文件名 公司名字 + 职位名字
  15. with open('python.html', mode='w', encoding='utf-8') as f:
  16.     f.write(content)
复制代码
 
可视化

代码
  1. import pandas as pd
  2. from pyecharts.charts import *
  3. from pyecharts import options as opts
  4. import re
  5. from pyecharts.globals import ThemeType
  6. from pyecharts.commons.utils import JsCode
复制代码
 
  1. df = pd.read_csv("招聘数据.csv")
  2. df.head()
复制代码
 
  1. df.info()
复制代码
 
  1. df['薪资'].unique()
  2. df['bottom']=df['薪资'].str.extract('^(\d+).*')
  3. df['top']=df['薪资'].str.extract('^.*?-(\d+).*')
  4. df['top'].fillna(df['bottom'],inplace=True)
  5. df['commision_pct']=df['薪资'].str.extract('^.*?·(\d{2})薪')
  6. df['commision_pct'].fillna(12,inplace=True)
  7. df['commision_pct']=df['commision_pct'].astype('float64')
  8. df['commision_pct']=df['commision_pct']/12
  9. df.dropna(inplace=True)
  10. 源码、解答、教程可加Q裙:832157862免费领取
  11. df['bottom'] = df['bottom'].astype('int64')
  12. df['top'] = df['top'].astype('int64')
  13. df['平均薪资'] = (df['bottom']+df['top'])/2*df['commision_pct']
  14. df['平均薪资'] = df['平均薪资'].astype('int64')
  15. df.head()
复制代码
 
  1. df['薪资'] = df['薪资'].apply(lambda x:re.sub('.*千/月', '0.3-0.7万/月', x))
  2. df["薪资"].unique()
复制代码
 
  1. df['bottom'] = df['薪资'].str.extract('^(.*?)-.*?')
  2. df['top'] = df['薪资'].str.extract('^.*?-(\d\.\d|\d)')
  3. df.dropna(inplace=True)
  4. df['bottom'] = df['bottom'].astype('float64')
  5. df['top'] = df['top'].astype('float64')
  6. df['平均薪资'] = (df['bottom']+df['top'])/2 * 10
  7. df.head()
复制代码
 
  1. mean = df.groupby('学历')['平均薪资'].mean().sort_values()
  2. x = mean.index.tolist()
  3. y = mean.values.tolist()
  4. c = (
  5.     Bar()
  6.     .add_xaxis(x)
  7.     .add_yaxis(
  8.         "学历",
  9.         y
  10.     )
  11.     .set_global_opts(title_opts=opts.TitleOpts(title="不同学历的平均薪资"),datazoom_opts=opts.DataZoomOpts())
  12.     .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
  13. )
  14. c.render_notebook()
复制代码
 
  1. color_js = """new echarts.graphic.LinearGradient(0, 1, 0, 0,
  2.     [{offset: 0, color: '#63e6be'}, {offset: 1, color: '#0b7285'}], false)"""
  3. color_js1 = """new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  4.                             offset: 0,
  5.                             color: '#ed1941'
  6.                         }, {
  7.                             offset: 1,
  8.                             color: '#009ad6'
  9.                         }], false)"""
  10. dq = df.groupby('城市')['职位'].count().to_frame('数量').sort_values(by='数量',ascending=False).reset_index()
  11. x_data = dq['城市'].values.tolist()[:20]
  12. y_data = dq['数量'].values.tolist()[:20]
  13. b1 = (
  14.         Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK,bg_color=JsCode(color_js1),width='1000px',height='600px'))
  15.         .add_xaxis(x_data)
  16.         .add_yaxis('',
  17.                    y_data ,
  18.                    category_gap="50%",
  19.                    label_opts=opts.LabelOpts(
  20.                         font_size=12,
  21.                         color='yellow',
  22.                         font_weight='bold',
  23.                         font_family='monospace',
  24.                         position='insideTop',  
  25.                         formatter = '{b}\n{c}'  
  26.                     ),
  27.                   )
  28.         .set_series_opts(
  29.             itemstyle_opts={
  30.                 "normal": {
  31.                     "color": JsCode(color_js),
  32.                     "barBorderRadius": [15, 15, 0, 0],
  33.                     "shadowColor": "rgb(0, 160, 221)",
  34.                 }
  35.             }
  36.         )
  37.         .set_global_opts(
  38.             title_opts=opts.TitleOpts(title='招 聘 数 量 前 20 的 城 市 区 域',
  39.                                        title_textstyle_opts=opts.TextStyleOpts(color="yellow"),
  40.                                        pos_top='7%',pos_left = 'center'
  41.                                      ),
  42.             legend_opts=opts.LegendOpts(is_show=False),
  43.             xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
  44.             yaxis_opts=opts.AxisOpts(name="",
  45.                                      name_location='middle',
  46.                                      name_gap=40,
  47.                                      name_textstyle_opts=opts.TextStyleOpts(font_size=16)),
  48.                          datazoom_opts=[opts.DataZoomOpts(range_start=1,range_end=50)]
  49.                         )
  50.     )
  51. b1.render_notebook()
复制代码
 
  1. boss = df['学历'].value_counts()
  2. x = boss.index.tolist()
  3. y = boss.values.tolist()
  4. data_pair = [list(z) for z in zip(x, y)]
  5. c = (
  6.     Pie(init_opts=opts.InitOpts(width="1000px", height="600px", bg_color="#2c343c"))
  7.     .add(
  8.         series_name="学历需求占比",
  9.         data_pair=data_pair,
  10.         label_opts=opts.LabelOpts(is_show=False, position="center", color="rgba(255, 255, 255, 0.3)"),
  11.     )
  12.     .set_series_opts(
  13.         tooltip_opts=opts.TooltipOpts(
  14.             trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"
  15.         ),
  16.         label_opts=opts.LabelOpts(color="rgba(255, 255, 255, 0.3)"),
  17.     )
  18.     .set_global_opts(
  19.         title_opts=opts.TitleOpts(
  20.             title="学历需求占比",
  21.             pos_left="center",
  22.             pos_top="20",
  23.             title_textstyle_opts=opts.TextStyleOpts(color="#fff"),
  24.         ),
  25.         legend_opts=opts.LegendOpts(is_show=False),
  26.     )
  27.     .set_colors(["#D53A35", "#334B5C", "#61A0A8", "#D48265", "#749F83"])
  28. )
  29. c.render_notebook()
复制代码
 
  1. boss = df['经验'].value_counts()
  2. x = boss.index.tolist()
  3. y = boss.values.tolist()
  4. data_pair = [list(z) for z in zip(x, y)]
  5. c = (
  6.     Pie(init_opts=opts.InitOpts(width="1000px", height="600px", bg_color="#2c343c"))
  7.     .add(
  8.         series_name="经验需求占比",
  9.         data_pair=data_pair,
  10.         label_opts=opts.LabelOpts(is_show=False, position="center", color="rgba(255, 255, 255, 0.3)"),
  11.     )
  12.     .set_series_opts(
  13.         tooltip_opts=opts.TooltipOpts(
  14.             trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"
  15.         ),
  16.         label_opts=opts.LabelOpts(color="rgba(255, 255, 255, 0.3)"),
  17.     )
  18.     .set_global_opts(
  19.         title_opts=opts.TitleOpts(
  20.             title="经验需求占比",
  21.             pos_left="center",
  22.             pos_top="20",
  23.             title_textstyle_opts=opts.TextStyleOpts(color="#fff"),
  24.         ),
  25.         legend_opts=opts.LegendOpts(is_show=False),
  26.     )
  27.     .set_colors(["#D53A35", "#334B5C", "#61A0A8", "#D48265", "#749F83"])
  28. )
  29. c.render_notebook()
复制代码
 
  1. boss = df['公司领域'].value_counts()
  2. x = boss.index.tolist()
  3. y = boss.values.tolist()
  4. data_pair = [list(z) for z in zip(x, y)]
  5. c = (
  6.     Pie(init_opts=opts.InitOpts(width="1000px", height="600px", bg_color="#2c343c"))
  7.     .add(
  8.         series_name="公司领域占比",
  9.         data_pair=data_pair,
  10.         label_opts=opts.LabelOpts(is_show=False, position="center", color="rgba(255, 255, 255, 0.3)"),
  11.     )
  12.     .set_series_opts(
  13.         tooltip_opts=opts.TooltipOpts(
  14.             trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"
  15.         ),
  16.         label_opts=opts.LabelOpts(color="rgba(255, 255, 255, 0.3)"),
  17.     )
  18.     .set_global_opts(
  19.         title_opts=opts.TitleOpts(
  20.             title="公司领域占比",
  21.             pos_left="center",
  22.             pos_top="20",
  23.             title_textstyle_opts=opts.TextStyleOpts(color="#fff"),
  24.         ),
  25.         legend_opts=opts.LegendOpts(is_show=False),
  26.     )
  27.     .set_colors(["#D53A35", "#334B5C", "#61A0A8", "#D48265", "#749F83"])
  28. )
  29. c.render_notebook()
复制代码
 
  1. from pyecharts import options as opts
  2. from pyecharts.charts import Pie
  3. from pyecharts.faker import Faker
  4. boss = df['经验'].value_counts()
  5. x = boss.index.tolist()
  6. y = boss.values.tolist()
  7. data_pair = [list(z) for z in zip(x, y)]
  8. c = (
  9.     Pie()
  10.     .add("", data_pair)
  11.     .set_colors(["blue", "green", "yellow", "red", "pink", "orange", "purple"])
  12.     .set_global_opts(title_opts=opts.TitleOpts(title="经验要求占比"))
  13.     .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
  14. )
  15. c.render_notebook()
复制代码
 
  1. from pyecharts import options as opts
  2. from pyecharts.charts import Pie
  3. from pyecharts.faker import Faker
  4. boss = df['经验'].value_counts()
  5. x = boss.index.tolist()
  6. y = boss.values.tolist()
  7. data_pair = [list(z) for z in zip(x, y)]
  8. c = (
  9.     Pie()
  10.     .add(
  11.         "",
  12.         data_pair,
  13.         radius=["40%", "55%"],
  14.         label_opts=opts.LabelOpts(
  15.             position="outside",
  16.             formatter="{a|{a}}{abg|}\n{hr|}\n {b|{b}: }{c}  {per|{d}%}  ",
  17.             background_color="#eee",
  18.             border_color="#aaa",
  19.             border_width=1,
  20.             border_radius=4,
  21.             rich={
  22.                 "a": {"color": "#999", "lineHeight": 22, "align": "center"},
  23.                 "abg": {
  24.                     "backgroundColor": "#e3e3e3",
  25.                     "width": "100%",
  26.                     "align": "right",
  27.                     "height": 22,
  28.                     "borderRadius": [4, 4, 0, 0],
  29.                 },
  30.                 "hr": {
  31.                     "borderColor": "#aaa",
  32.                     "width": "100%",
  33.                     "borderWidth": 0.5,
  34.                     "height": 0,
  35.                 },
  36.                 "b": {"fontSize": 16, "lineHeight": 33},
  37.                 "per": {
  38.                     "color": "#eee",
  39.                     "backgroundColor": "#334455",
  40.                     "padding": [2, 4],
  41.                     "borderRadius": 2,
  42.                 },
  43.             },
  44.         ),
  45.     )
  46.     .set_global_opts(title_opts=opts.TitleOpts(title="Pie-富文本示例"))
  47.    
  48. )
  49. c.render_notebook()
复制代码
 
  1. gsly = df['公司领域'].value_counts()[:10]
  2. x1 = gsly.index.tolist()
  3. y1 = gsly.values.tolist()
  4. c = (
  5.     Bar()
  6.     .add_xaxis(x1)
  7.     .add_yaxis(
  8.         "公司领域",
  9.         y1
  10.     )
  11.     .set_global_opts(title_opts=opts.TitleOpts(title="公司领域"),datazoom_opts=opts.DataZoomOpts())
  12.     .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
  13. )
  14. c.render_notebook()
复制代码
 
  1. gsgm = df['公司规模'].value_counts()[1:10]
  2. x2 = gsgm.index.tolist()
  3. y2 = gsgm.values.tolist()
  4. c = (
  5.     Bar()
  6.     .add_xaxis(x2)
  7.     .add_yaxis(
  8.         "公司规模",
  9.         y2
  10.     )
  11.     .set_global_opts(title_opts=opts.TitleOpts(title="公司规模"),datazoom_opts=opts.DataZoomOpts())
  12.     .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
  13. )
  14. c.render_notebook()
复制代码
 
  1. import stylecloud
  2. from PIL import Image
  3. welfares = df['福利'].dropna(how='all').values.tolist()
  4. welfares_list = []
  5. for welfare in welfares:
  6.     welfares_list += welfare.split(',')
  7. pic_name = '福利词云.png'
  8. stylecloud.gen_stylecloud(
  9.     text=' '.join(welfares_list),
  10.     font_path='msyh.ttc',
  11.     palette='cartocolors.qualitative.Bold_5',
  12.     max_font_size=100,
  13.     icon_name='fas fa-yen-sign',
  14.     background_color='#212529',
  15.     output_name=pic_name,
  16.     )
  17. Image.open(pic_name)
复制代码
 
部分效果展示

 
 
 
 
 
 
 
 
 
 
尾语

好了,我的这篇文章写到这里就结束啦!
有更多建议或问题可以评论区或私信我哦!一起加油努力叭(ง •_•)ง
喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!
 
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4