百木园-与人分享,
就是让自己快乐。

Python采集招聘数据信息(+详情页)并实现可视化


本篇代码提供者: 青灯教育-自游老师


[环境使用]:

  • Python 3.8
  • Pycharm

[模块使用]:

  • requests >>> pip install requests
  • re
  • json
  • csv

如果安装python第三方模块:

  1. win + R 输入 cmd 点击确定, 输入安装命令 pip install 模块名 (pip install requests) 回车
  2. 在pycharm中点击Terminal(终端) 输入安装命令

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

  1. 选择file(文件) >>> setting(设置) >>> Project(项目) >>> python interpreter(python解释器)

  2. 点击齿轮, 选择add

  3. 添加python安装路径


pycharm如何安装插件?

  1. 选择file(文件) >>> setting(设置) >>> Plugins(插件)

  2. 点击 Marketplace 输入想要安装的插件名字 比如:翻译插件 输入 translation / 汉化插件 输入 Chinese

  3. 选择相应的插件点击 install(安装) 即可

  4. 安装成功之后 是会弹出 重启pycharm的选项 点击确定, 重启即可生效


基本流程思路: <可以通用>

一. 数据来源分析

网页开发者工具进行抓包分析....

  1. F12打开开发者工具, 刷新网页
  2. 通过关键字进行搜索, 找到相应的数据, 查看response响应数据
  3. 确定数据之后, 查看headers确定请求url地址 请求方式 以及 请求参数

二. 代码实现过程:

  1. 发送请求, 用python代码模拟浏览器对于url地址发送请求
  2. 获取数据, 获取服务器返回response响应数据
  3. 解析数据, 提取我们想要招聘信息数据
  4. 保存数据, 保存到表格文件里面

代码

导入模块

# 导入数据请求模块
import requests
# 导入正则表达式模块
import re
# 导入json模块
import json
# 导入格式化输出模块
import pprint
# 导入csv模块
import csv
# 导入时间模块
import time
# 导入随机模块
import random
# 有没有用utf-8保存表格数据,乱码的?
f = open(\'data多页_1.csv\', mode=\'a\', encoding=\'utf-8\', newline=\'\')  # 打开一个文件 data.csv
csv_writer = csv.DictWriter(f, fieldnames=[
    \'职位\',
    \'城市\',
    \'经验\',
    \'学历\',
    \'薪资\',
    \'公司\',
    \'福利待遇\',
    \'公司领域\',
    \'公司规模\',
    \'公司类型\',
    \'发布日期\',
    \'职位详情页\',
    \'公司详情页\',
])
csv_writer.writeheader()

 

1. 发送请求,

用python代码模拟浏览器对于url地址发送请求

不要企图一节课, 掌握所有内容, 要学习听懂思路, 每一步我们为什么这么做...
知道headers 1
不知道headers 2

headers 请求头, 作用伪装python代码, 伪装成浏览器
字典形式, 构建完整键值对

如果当你headers伪装不够的时候, 你可能会被服务器识别出来, 你是爬虫程序, 从而不给你相应的数据内容

for page in range(1, 15):
    print(f\'正在采集第{page}页的数据内容\')
    time.sleep(random.randint(1, 2))
    url = f\'https://search.51job.com/list/010000%252C020000%252C030200%252C040000%252C090200,000000,0000,00,9,99,python,2,{page}.html\'
    headers = {
        \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36\'
    }
    response = requests.get(url=url, headers=headers)
    print(response)  # <Response [200]> 响应对象

 

2. 获取数据

得到数据, 不是你想要数据内容, 你可能是被反爬了, 要多加一些伪装 <小伏笔>

# print(response.text)  字符串数据类型

 

3. 解析数据, 提取我们想要数据内容

re.findall() 就是从什么地方去找什么样数据内容

[0] 表示提取列表里面第一个元素 ---> list index out of range 所以你的列表是空列表

用正则表达式/css/xpath提取数据返回是空列表 ---> 1. 你语法写错 2. response.text 没有你想要数据

---> 是不是被反爬(验证码 需要登陆) 是不是headers参数给少了 是不是被封IP

    html_data = re.findall(\'window.__SEARCH_RESULT__ = (.*?)</script>\', response.text)[0]
    # print(html_data)
    json_data = json.loads(html_data)
    # pprint.pprint(json_data)
    # 通过字典取值方法 把职位信息列表提取出来, 通过for循环遍历一个一个提取职位信息
    for index in json_data[\'engine_jds\']:
        # 根据冒号左边的内容, 提取冒号右边的内容
        # pprint.pprint(index)
        try:
            dit = {
                \'职位\': index[\'job_title\'],
                \'城市\': index[\'attribute_text\'][0],
                \'经验\': index[\'attribute_text\'][1],
                \'学历\': index[\'attribute_text\'][2],
                \'薪资\': index[\'providesalary_text\'],
                \'公司\': index[\'company_name\'],
                \'福利待遇\': index[\'jobwelf\'],
                \'公司领域\': index[\'companyind_text\'],
                \'公司规模\': index[\'companysize_text\'],
                \'公司类型\': index[\'companytype_text\'],
                \'发布日期\': index[\'issuedate\'],
                \'职位详情页\': index[\'job_href\'],
                \'公司详情页\': index[\'company_href\'],
            }
            csv_writer.writerow(dit)
            print(dit)
        except:
            pass

 

详情页数据

----> 爬虫基本思路是什么?

数据来源分析

请求响应 请求那个网站呢? 网址是什么 请求方式是什么 请求参数要什么?

发送请求 ---> 获取数据 ---> 解析数据 ---> 保存数据

导入模块

import requests
import parsel
url = \'https://jobs.51job.com/shanghai-jdq/137393082.html?s=sou_sou_soulb&t=0_0\'
headers = {
    \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36\',
}
response = requests.get(url=url, headers=headers)
response.encoding = response.apparent_encoding  # 自动识别编码
print(response.text)
selector = parsel.Selector(response.text)
content_1 = selector.css(\'.cn\').get()
content_2 = selector.css(\'.tCompany_main\').get()
content = content_1 + content_2
# 文件名 公司名字 + 职位名字
with open(\'python.html\', mode=\'w\', encoding=\'utf-8\') as f:
    f.write(content)

 

可视化

代码

import pandas as pd
from pyecharts.charts import *
from pyecharts import options as opts
import re
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode

 

df = pd.read_csv(\"招聘数据.csv\")
df.head()

 

df.info()

 

df[\'薪资\'].unique()
df[\'bottom\']=df[\'薪资\'].str.extract(\'^(\\d+).*\')
df[\'top\']=df[\'薪资\'].str.extract(\'^.*?-(\\d+).*\')
df[\'top\'].fillna(df[\'bottom\'],inplace=True)

df[\'commision_pct\']=df[\'薪资\'].str.extract(\'^.*?·(\\d{2})薪\')
df[\'commision_pct\'].fillna(12,inplace=True)
df[\'commision_pct\']=df[\'commision_pct\'].astype(\'float64\')
df[\'commision_pct\']=df[\'commision_pct\']/12

df.dropna(inplace=True)
源码、解答、教程可加Q裙:832157862免费领取
df[\'bottom\'] = df[\'bottom\'].astype(\'int64\')
df[\'top\'] = df[\'top\'].astype(\'int64\')
df[\'平均薪资\'] = (df[\'bottom\']+df[\'top\'])/2*df[\'commision_pct\']
df[\'平均薪资\'] = df[\'平均薪资\'].astype(\'int64\')

df.head()

 

df[\'薪资\'] = df[\'薪资\'].apply(lambda x:re.sub(\'.*千/月\', \'0.3-0.7万/月\', x))
df[\"薪资\"].unique()

 

df[\'bottom\'] = df[\'薪资\'].str.extract(\'^(.*?)-.*?\')
df[\'top\'] = df[\'薪资\'].str.extract(\'^.*?-(\\d\\.\\d|\\d)\')
df.dropna(inplace=True)
df[\'bottom\'] = df[\'bottom\'].astype(\'float64\')
df[\'top\'] = df[\'top\'].astype(\'float64\')
df[\'平均薪资\'] = (df[\'bottom\']+df[\'top\'])/2 * 10
df.head()

 

mean = df.groupby(\'学历\')[\'平均薪资\'].mean().sort_values()
x = mean.index.tolist()
y = mean.values.tolist()
c = (
    Bar()
    .add_xaxis(x)
    .add_yaxis(
        \"学历\",
        y
    )
    .set_global_opts(title_opts=opts.TitleOpts(title=\"不同学历的平均薪资\"),datazoom_opts=opts.DataZoomOpts())
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
)
c.render_notebook()

 

color_js = \"\"\"new echarts.graphic.LinearGradient(0, 1, 0, 0,
    [{offset: 0, color: \'#63e6be\'}, {offset: 1, color: \'#0b7285\'}], false)\"\"\"

color_js1 = \"\"\"new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                            offset: 0,
                            color: \'#ed1941\'
                        }, {
                            offset: 1,
                            color: \'#009ad6\'
                        }], false)\"\"\"

dq = df.groupby(\'城市\')[\'职位\'].count().to_frame(\'数量\').sort_values(by=\'数量\',ascending=False).reset_index()
x_data = dq[\'城市\'].values.tolist()[:20]
y_data = dq[\'数量\'].values.tolist()[:20]
b1 = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK,bg_color=JsCode(color_js1),width=\'1000px\',height=\'600px\'))
        .add_xaxis(x_data)
        .add_yaxis(\'\',
                   y_data ,
                   category_gap=\"50%\",
                   label_opts=opts.LabelOpts(
                        font_size=12,
                        color=\'yellow\',
                        font_weight=\'bold\', 
                        font_family=\'monospace\',
                        position=\'insideTop\',  
                        formatter = \'{b}\\n{c}\'  
                    ),
                  )
        .set_series_opts(
            itemstyle_opts={
                \"normal\": {
                    \"color\": JsCode(color_js),
                    \"barBorderRadius\": [15, 15, 0, 0],
                    \"shadowColor\": \"rgb(0, 160, 221)\",
                }
            }
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title=\'招 聘 数 量 前 20 的 城 市 区 域\',
                                       title_textstyle_opts=opts.TextStyleOpts(color=\"yellow\"),
                                       pos_top=\'7%\',pos_left = \'center\'
                                     ),
            legend_opts=opts.LegendOpts(is_show=False),
            xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
            yaxis_opts=opts.AxisOpts(name=\"\",
                                     name_location=\'middle\',
                                     name_gap=40,
                                     name_textstyle_opts=opts.TextStyleOpts(font_size=16)),
                         datazoom_opts=[opts.DataZoomOpts(range_start=1,range_end=50)]
                        )

    )
b1.render_notebook()

 

boss = df[\'学历\'].value_counts()
x = boss.index.tolist()
y = boss.values.tolist()
data_pair = [list(z) for z in zip(x, y)]
c = (
    Pie(init_opts=opts.InitOpts(width=\"1000px\", height=\"600px\", bg_color=\"#2c343c\"))
    .add(
        series_name=\"学历需求占比\",
        data_pair=data_pair,
        label_opts=opts.LabelOpts(is_show=False, position=\"center\", color=\"rgba(255, 255, 255, 0.3)\"),
    )
    .set_series_opts(
        tooltip_opts=opts.TooltipOpts(
            trigger=\"item\", formatter=\"{a} <br/>{b}: {c} ({d}%)\"
        ),
        label_opts=opts.LabelOpts(color=\"rgba(255, 255, 255, 0.3)\"),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title=\"学历需求占比\",
            pos_left=\"center\",
            pos_top=\"20\",
            title_textstyle_opts=opts.TextStyleOpts(color=\"#fff\"),
        ),
        legend_opts=opts.LegendOpts(is_show=False),
    )
    .set_colors([\"#D53A35\", \"#334B5C\", \"#61A0A8\", \"#D48265\", \"#749F83\"])
)
c.render_notebook()

 

boss = df[\'经验\'].value_counts()
x = boss.index.tolist()
y = boss.values.tolist()
data_pair = [list(z) for z in zip(x, y)]
c = (
    Pie(init_opts=opts.InitOpts(width=\"1000px\", height=\"600px\", bg_color=\"#2c343c\"))
    .add(
        series_name=\"经验需求占比\",
        data_pair=data_pair,
        label_opts=opts.LabelOpts(is_show=False, position=\"center\", color=\"rgba(255, 255, 255, 0.3)\"),
    )
    .set_series_opts(
        tooltip_opts=opts.TooltipOpts(
            trigger=\"item\", formatter=\"{a} <br/>{b}: {c} ({d}%)\"
        ),
        label_opts=opts.LabelOpts(color=\"rgba(255, 255, 255, 0.3)\"),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title=\"经验需求占比\",
            pos_left=\"center\",
            pos_top=\"20\",
            title_textstyle_opts=opts.TextStyleOpts(color=\"#fff\"),
        ),
        legend_opts=opts.LegendOpts(is_show=False),
    )
    .set_colors([\"#D53A35\", \"#334B5C\", \"#61A0A8\", \"#D48265\", \"#749F83\"])
)
c.render_notebook()

 

boss = df[\'公司领域\'].value_counts()
x = boss.index.tolist()
y = boss.values.tolist()
data_pair = [list(z) for z in zip(x, y)]
c = (
    Pie(init_opts=opts.InitOpts(width=\"1000px\", height=\"600px\", bg_color=\"#2c343c\"))
    .add(
        series_name=\"公司领域占比\",
        data_pair=data_pair,
        label_opts=opts.LabelOpts(is_show=False, position=\"center\", color=\"rgba(255, 255, 255, 0.3)\"),
    )
    .set_series_opts(
        tooltip_opts=opts.TooltipOpts(
            trigger=\"item\", formatter=\"{a} <br/>{b}: {c} ({d}%)\"
        ),
        label_opts=opts.LabelOpts(color=\"rgba(255, 255, 255, 0.3)\"),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title=\"公司领域占比\",
            pos_left=\"center\",
            pos_top=\"20\",
            title_textstyle_opts=opts.TextStyleOpts(color=\"#fff\"),
        ),
        legend_opts=opts.LegendOpts(is_show=False),
    )
    .set_colors([\"#D53A35\", \"#334B5C\", \"#61A0A8\", \"#D48265\", \"#749F83\"])
)
c.render_notebook()

 

from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker
boss = df[\'经验\'].value_counts()
x = boss.index.tolist()
y = boss.values.tolist()
data_pair = [list(z) for z in zip(x, y)]
c = (
    Pie()
    .add(\"\", data_pair)
    .set_colors([\"blue\", \"green\", \"yellow\", \"red\", \"pink\", \"orange\", \"purple\"])
    .set_global_opts(title_opts=opts.TitleOpts(title=\"经验要求占比\"))
    .set_series_opts(label_opts=opts.LabelOpts(formatter=\"{b}: {c}\"))
)
c.render_notebook()

 

from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker
boss = df[\'经验\'].value_counts()
x = boss.index.tolist()
y = boss.values.tolist()
data_pair = [list(z) for z in zip(x, y)]

c = (
    Pie()
    .add(
        \"\",
        data_pair,
        radius=[\"40%\", \"55%\"],
        label_opts=opts.LabelOpts(
            position=\"outside\",
            formatter=\"{a|{a}}{abg|}\\n{hr|}\\n {b|{b}: }{c}  {per|{d}%}  \",
            background_color=\"#eee\",
            border_color=\"#aaa\",
            border_width=1,
            border_radius=4,
            rich={
                \"a\": {\"color\": \"#999\", \"lineHeight\": 22, \"align\": \"center\"},
                \"abg\": {
                    \"backgroundColor\": \"#e3e3e3\",
                    \"width\": \"100%\",
                    \"align\": \"right\",
                    \"height\": 22,
                    \"borderRadius\": [4, 4, 0, 0],
                },
                \"hr\": {
                    \"borderColor\": \"#aaa\",
                    \"width\": \"100%\",
                    \"borderWidth\": 0.5,
                    \"height\": 0,
                },
                \"b\": {\"fontSize\": 16, \"lineHeight\": 33},
                \"per\": {
                    \"color\": \"#eee\",
                    \"backgroundColor\": \"#334455\",
                    \"padding\": [2, 4],
                    \"borderRadius\": 2,
                },
            },
        ),
    )
    .set_global_opts(title_opts=opts.TitleOpts(title=\"Pie-富文本示例\"))
    
)
c.render_notebook()

 

gsly = df[\'公司领域\'].value_counts()[:10]
x1 = gsly.index.tolist()
y1 = gsly.values.tolist()
c = (
    Bar()
    .add_xaxis(x1)
    .add_yaxis(
        \"公司领域\",
        y1
    )
    .set_global_opts(title_opts=opts.TitleOpts(title=\"公司领域\"),datazoom_opts=opts.DataZoomOpts())
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
)
c.render_notebook()

 

gsgm = df[\'公司规模\'].value_counts()[1:10]
x2 = gsgm.index.tolist()
y2 = gsgm.values.tolist()
c = (
    Bar()
    .add_xaxis(x2)
    .add_yaxis(
        \"公司规模\",
        y2
    )
    .set_global_opts(title_opts=opts.TitleOpts(title=\"公司规模\"),datazoom_opts=opts.DataZoomOpts())
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
)
c.render_notebook()

 

import stylecloud
from PIL import Image
welfares = df[\'福利\'].dropna(how=\'all\').values.tolist()
welfares_list = []
for welfare in welfares:
    welfares_list += welfare.split(\'\')
pic_name = \'福利词云.png\'
stylecloud.gen_stylecloud(
    text=\' \'.join(welfares_list),
    font_path=\'msyh.ttc\',
    palette=\'cartocolors.qualitative.Bold_5\',
    max_font_size=100,
    icon_name=\'fas fa-yen-sign\',
    background_color=\'#212529\',
    output_name=pic_name,
    )
Image.open(pic_name)

 

部分效果展示

 

 

 

 

 

 

 

 

 

 

尾语

好了,我的这篇文章写到这里就结束啦!

有更多建议或问题可以评论区或私信我哦!一起加油努力叭(ง •_•)ง

喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!

 

 


来源:https://www.cnblogs.com/Qqun261823976/p/16428865.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » Python采集招聘数据信息(+详情页)并实现可视化

相关推荐

  • 暂无文章