溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏

發(fā)布時(shí)間:2021-10-26 10:19:25 來源:億速云 閱讀:186 作者:柒染 欄目:大數(shù)據(jù)

如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

項(xiàng)目背景

隨著科技的飛速發(fā)展,數(shù)據(jù)呈現(xiàn)爆發(fā)式的增長(zhǎng),任何人都擺脫不了與數(shù)據(jù)打交道,社會(huì)對(duì)于“數(shù)據(jù)”方面的人才需求也在不斷增大。因此了解當(dāng)下企業(yè)究竟需要招聘什么樣的人才?需要什么樣的技能?不管是對(duì)于在校生,還是對(duì)于求職者來說,都顯得很有必要。

本文基于這個(gè)問題,針對(duì)51job招聘網(wǎng)站,爬取了全國(guó)范圍內(nèi)大數(shù)據(jù)、數(shù)據(jù)分析、數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)、人工智能等相關(guān)崗位的招聘信息。分析比較了不同崗位的薪資、學(xué)歷要求;分析比較了不同區(qū)域、行業(yè)對(duì)相關(guān)人才的需求情況;分析比較了不同崗位的知識(shí)、技能要求等。

做完以后的項(xiàng)目效果如下:

如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏

信息的爬取

  • 爬取崗位:大數(shù)據(jù)、數(shù)據(jù)分析、機(jī)器學(xué)習(xí)、人工智能等相關(guān)崗位;

  • 爬取字段:公司名、崗位名、工作地址、薪資、發(fā)布時(shí)間、工作描述、公司類型、員工人數(shù)、所屬行業(yè);

  • 說明:基于51job招聘網(wǎng)站,我們搜索全國(guó)對(duì)于“數(shù)據(jù)”崗位的需求,大概有2000頁(yè)。我們爬取的字段,既有一級(jí)頁(yè)面的相關(guān)信息,還有二級(jí)頁(yè)面的部分信息;

  • 爬取思路:先針對(duì)某一頁(yè)數(shù)據(jù)的一級(jí)頁(yè)面做一個(gè)解析,然后再進(jìn)行二級(jí)頁(yè)面做一個(gè)解析,最后再進(jìn)行翻頁(yè)操作;

  • 使用工具:Python+requests+lxml+pandas+time

  • 網(wǎng)站解析方式:Xpath

1、導(dǎo)入相關(guān)庫(kù)

 
import requests
import pandas as pd
from pprint import pprint
from lxml import etree
import time
import warnings
warnings.filterwarnings("ignore")

2、關(guān)于翻頁(yè)的說明

 
# 第一頁(yè)的特點(diǎn)
https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,1.html?
# 第二頁(yè)的特點(diǎn)
https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,2.html?
# 第三頁(yè)的特點(diǎn)
https://search.51job.com/list/000000,000000,0000,00,9,99,%25E6%2595%25B0%25E6%258D%25AE,2,3.html?

注意:通過對(duì)于頁(yè)面的觀察,可以看出,就一個(gè)地方的數(shù)字變化了,因此只需要做字符串拼接,然后循環(huán)爬取即可。

3、完整的爬取代碼

 
import requests
import pandas as pd
from pprint import pprint
from lxml import etree
import time
import warnings
warnings.filterwarnings("ignore")

for i in range(1,1501):
    print("正在爬取第">

這里可以看到,我們爬取了1000多頁(yè)的數(shù)據(jù)做最終的分析。因此每爬取一頁(yè)的數(shù)據(jù),做一次數(shù)據(jù)存儲(chǔ),避免最終一次性存儲(chǔ)導(dǎo)致失敗。同時(shí)根據(jù)自己的測(cè)試,有一些頁(yè)數(shù)進(jìn)行數(shù)據(jù)存儲(chǔ),會(huì)導(dǎo)致失敗,為了不影響后面代碼的執(zhí)行,我們使用了“try-except”異常處理。

在一級(jí)頁(yè)面中,我們爬取了“崗位名稱”,“公司名稱”,“工作地點(diǎn)”,“工資”,“發(fā)布日期”,“二級(jí)網(wǎng)址的url”這幾個(gè)字段。

在二級(jí)頁(yè)面中,我們爬取了“經(jīng)驗(yàn)、學(xué)歷信息”,“崗位描述”,“公司類型”,“公司規(guī)?!?,“所屬行業(yè)”這幾個(gè)字段。

數(shù)據(jù)預(yù)處理

從爬取到的數(shù)據(jù)中截取部分做了一個(gè)展示,可以看出數(shù)據(jù)很亂。雜亂的數(shù)據(jù)并不利于我們的分析,因此需要根據(jù)研究的目標(biāo)做一個(gè)數(shù)據(jù)預(yù)處理,得到我們最終可以用來做可視化展示的數(shù)據(jù)。

1、相關(guān)庫(kù)的導(dǎo)入及數(shù)據(jù)的讀取

df = pd.read_csv(r"G:\8泰迪\python_project\51_job\job_info1.csv",engine="python",header=None)
# 為數(shù)據(jù)框指定行索引
df.index = range(len(df))
# 為數(shù)據(jù)框指定列索引
df.columns = ["崗位名","公司名","工作地點(diǎn)","工資","發(fā)布日期","經(jīng)驗(yàn)與學(xué)歷","公司類型","公司規(guī)模","行業(yè)","工作描述"]

2、數(shù)據(jù)去重

  • 我們認(rèn)為一個(gè)公司的公司名和和發(fā)布的崗位名一致,就看作是重復(fù)值。因此,使用drop_duplicates(subset=[])函數(shù),基于“崗位名”和“公司名”做一個(gè)重復(fù)值的剔除。

# 去重之前的記錄數(shù)
print("去重之前的記錄數(shù)",df.shape)
# 記錄去重
df.drop_duplicates(subset=["公司名","崗位名"],inplace=True)
# 去重之后的記錄數(shù)
print("去重之后的記錄數(shù)",df.shape)

3、崗位名字段的處理

① 崗位名字段的探索

df["崗位名"].value_counts()
df["崗位名"] = df["崗位名"].apply(lambda x:x.lower())
  • 說明:首先我們對(duì)每個(gè)崗位出現(xiàn)的頻次做一個(gè)統(tǒng)計(jì),可以看出“崗位名字段”太雜亂,不便于我們做統(tǒng)計(jì)分析。接著我們將崗位名中的大寫英文字母統(tǒng)一轉(zhuǎn)換為小寫字母,也就是說“AI”和“Ai”屬于同一個(gè)東西。

② 構(gòu)造想要分析的目標(biāo)崗位,做一個(gè)數(shù)據(jù)篩選

job_list = ['數(shù)據(jù)分析', "數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)專員",'數(shù)據(jù)挖掘', '算法',
            '大數(shù)據(jù)','開發(fā)工程師', '運(yùn)營(yíng)', '軟件工程', '前端開發(fā)',
            '深度學(xué)習(xí)', 'ai', '數(shù)據(jù)庫(kù)', '數(shù)據(jù)庫(kù)', '數(shù)據(jù)產(chǎn)品',
            '客服', 'java', '.net', 'andrio', '人工智能', 'c++',
            '數(shù)據(jù)管理',"測(cè)試","運(yùn)維"]
job_list = np.array(job_list)
def rename(x=None,job_list=job_list):
    index = [i in x for i in job_list]
    if sum(index) > 0:
        return job_list[index][0]
    else:
        return x
job_info["崗位名"] = job_info["崗位名"].apply(rename)
job_info["崗位名"].value_counts()
# 數(shù)據(jù)統(tǒng)計(jì)、數(shù)據(jù)專員、數(shù)據(jù)分析統(tǒng)一歸為數(shù)據(jù)分析
job_info["崗位名"] = job_info["崗位名"].apply(lambda x:re.sub("數(shù)據(jù)專員","數(shù)據(jù)分析",x))
job_info["崗位名"] = job_info["崗位名"].apply(lambda x:re.sub("數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)分析",x))
  • 說明:首先我們構(gòu)造了如上七個(gè)目標(biāo)崗位的關(guān)鍵字眼。然后利用count()函數(shù)統(tǒng)計(jì)每一條記錄中,是否包含這七個(gè)關(guān)鍵字眼,如果包含就保留這個(gè)字段,不過不包含就刪除這個(gè)字段。最后查看篩選之后還剩余多少條記錄。

③ 目標(biāo)崗位標(biāo)準(zhǔn)化處理(由于目標(biāo)崗位太雜亂,我們需要統(tǒng)一一下)

job_list = ['數(shù)據(jù)分析', "數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)專員",'數(shù)據(jù)挖掘', '算法',
            '大數(shù)據(jù)','開發(fā)工程師', '運(yùn)營(yíng)', '軟件工程', '前端開發(fā)',
            '深度學(xué)習(xí)', 'ai', '數(shù)據(jù)庫(kù)', '數(shù)據(jù)庫(kù)', '數(shù)據(jù)產(chǎn)品',
            '客服', 'java', '.net', 'andrio', '人工智能', 'c++',
            '數(shù)據(jù)管理',"測(cè)試","運(yùn)維"]
job_list = np.array(job_list)
def rename(x=None,job_list=job_list):
    index = [i in x for i in job_list]
    if sum(index) > 0:
        return job_list[index][0]
    else:
        return x
job_info["崗位名"] = job_info["崗位名"].apply(rename)
job_info["崗位名"].value_counts()
# 數(shù)據(jù)統(tǒng)計(jì)、數(shù)據(jù)專員、數(shù)據(jù)分析統(tǒng)一歸為數(shù)據(jù)分析
job_info["崗位名"] = job_info["崗位名"].apply(lambda x:re.sub("數(shù)據(jù)專員","數(shù)據(jù)分析",x))
job_info["崗位名"] = job_info["崗位名"].apply(lambda x:re.sub("數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)分析",x))
  • 說明:首先我們定義了一個(gè)想要替換的目標(biāo)崗位job_list,將其轉(zhuǎn)換為ndarray數(shù)組。然后定義一個(gè)函數(shù),如果某條記錄包含job_list數(shù)組中的某個(gè)關(guān)鍵詞,那么就將該條記錄替換為這個(gè)關(guān)鍵詞,如果某條記錄包含job_list數(shù)組中的多個(gè)關(guān)鍵詞,我們只取第一個(gè)關(guān)鍵詞替換該條記錄。接著使用value_counts()函數(shù)統(tǒng)計(jì)一下替換后的各崗位的頻次。最后,我們將“數(shù)據(jù)專員”、“數(shù)據(jù)統(tǒng)計(jì)”統(tǒng)一歸為“數(shù)據(jù)分析”。

4、工資水平字段的處理

工資水平字段的數(shù)據(jù)類似于“20-30萬/年”、“2.5-3萬/月”和“3.5-4.5千/月”這樣的格式。我們需要做一個(gè)統(tǒng)一的變化,將數(shù)據(jù)格式轉(zhuǎn)換為“元/月”,然后取出這兩個(gè)數(shù)字,求一個(gè)平均值。

 
job_info["工資"].str[-1].value_counts()
job_info["工資"].str[-3].value_counts()

index1 = job_info["工資"].str[-1].isin(["年","月"])
index2 = job_info["工資"].str[-3].isin(["萬","千"])
job_info = job_info[index1 & index2]

def get_money_max_min(x):
    try:
        if x[-3] == "萬":
            z = [float(i)*10000 for i in re.findall("[0-9]+\.?[0-9]*",x)]
        elif x[-3] == "千":
            z = [float(i) * 1000 for i in re.findall("[0-9]+\.?[0-9]*", x)]
        if x[-1] == "年":
            z = [i/12 for i in z]
        return z
    except:
        return x

salary = job_info["工資"].apply(get_money_max_min)
job_info["最低工資"] = salary.str[0]
job_info["最高工資"] = salary.str[1]
job_info["工資水平"] = job_info[["最低工資","最高工資"]].mean(axis=1)
  • 說明:首先我們做了一個(gè)數(shù)據(jù)篩選,針對(duì)于每一條記錄,如果最后一個(gè)字在“年”和“月”中,同時(shí)第三個(gè)字在“萬”和“千”中,那么就保留這條記錄,否則就刪除。接著定義了一個(gè)函數(shù),將格式統(tǒng)一轉(zhuǎn)換為“元/月”。最后將最低工資和最高工資求平均值,得到最終的“工資水平”字段。

5、工作地點(diǎn)字段的處理

由于整個(gè)數(shù)據(jù)是關(guān)于全國(guó)的數(shù)據(jù),涉及到的城市也是特別多。我們需要自定義一個(gè)常用的目標(biāo)工作地點(diǎn)字段,對(duì)數(shù)據(jù)做一個(gè)統(tǒng)一處理。

#job_info["工作地點(diǎn)"].value_counts()
address_list = ['北京', '上海', '廣州', '深圳', '杭州', '蘇州', '長(zhǎng)沙',
                '武漢', '天津', '成都', '西安', '東莞', '合肥', '佛山',
                '寧波', '南京', '重慶', '長(zhǎng)春', '鄭州', '常州', '福州',
                '沈陽(yáng)', '濟(jì)南', '寧波', '廈門', '貴州', '珠海', '青島',
                '中山', '大連','昆山',"惠州","哈爾濱","昆明","南昌","無錫"]
address_list = np.array(address_list)

def rename(x=None,address_list=address_list):
    index = [i in x for i in address_list]
    if sum(index) > 0:
        return address_list[index][0]
    else:
        return x
job_info["工作地點(diǎn)"] = job_info["工作地點(diǎn)"].apply(rename)
  • 說明:首先我們定義了一個(gè)目標(biāo)工作地點(diǎn)列表,將其轉(zhuǎn)換為ndarray數(shù)組。接著定義了一個(gè)函數(shù),將原始工作地點(diǎn)記錄,替換為目標(biāo)工作地點(diǎn)中的城市。

6、公司類型字段的處理

這個(gè)很容易,就不詳細(xì)說明了。

 
job_info.loc[job_info["公司類型"].apply(lambda x:len(x)<6),"公司類型"] = np.nan
job_info["公司類型"] = job_info["公司類型"].str[2:-2]

7、行業(yè)字段的處理

每個(gè)公司的行業(yè)字段可能會(huì)有多個(gè)行業(yè)標(biāo)簽,但是我們默認(rèn)以第一個(gè)作為該公司的行業(yè)標(biāo)簽。

 
# job_info["行業(yè)"].value_counts()
job_info["行業(yè)"] = job_info["行業(yè)"].apply(lambda x:re.sub(",","/",x))
job_info.loc[job_info["行業(yè)"].apply(lambda x:len(x)<6),"行業(yè)"] = np.nan
job_info["行業(yè)"] = job_info["行業(yè)"].str[2:-2].str.split("/").str[0]

8、經(jīng)驗(yàn)與學(xué)歷字段的處理

關(guān)于這個(gè)字段的數(shù)據(jù)處理,我很是思考了一會(huì)兒,不太好敘述,放上代碼自己下去體會(huì)。

job_info["學(xué)歷"] = job_info["經(jīng)驗(yàn)與學(xué)歷"].apply(lambda x:re.findall("本科|大專|應(yīng)屆生|在校生|碩士",x))
def func(x):
    if len(x) == 0:
        return np.nan
    elif len(x) == 1 or len(x) == 2:
        return x[0]
    else:
        return x[2]
job_info["學(xué)歷"] = job_info["學(xué)歷"].apply(func)

9、工作描述字段的處理

對(duì)于每一行記錄,我們?nèi)コS迷~以后,做一個(gè)jieba分詞。

with open(r"G:\8泰迪\python_project\51_job\stopword.txt","r") as f:
    stopword = f.read()
stopword = stopword.split()
stopword = stopword + ["任職","職位"," "]

job_info["工作描述"] = job_info["工作描述"].str[2:-2].apply(lambda x:x.lower()).apply(lambda x:"".join(x))\
    .apply(jieba.lcut).apply(lambda x:[i for i in x if i not in stopword])
job_info.loc[job_info["工作描述"].apply(lambda x:len(x) < 6),"工作描述"] = np.nan

10、公司規(guī)模字段的處理

#job_info["公司規(guī)模"].value_counts()
def func(x):
    if x == "['少于50人']":
        return "<50"
    elif x == "['50-150人']":
        return "50-150"
    elif x == "['150-500人']":
        return '150-500'
    elif x == "['500-1000人']":
        return '500-1000'
    elif x == "['1000-5000人']":
        return '1000-5000'
    elif x == "['5000-10000人']":
        return '5000-10000'
    elif x == "['10000人以上']":
        return ">10000"
    else:
        return np.nan
job_info["公司規(guī)模"] = job_info["公司規(guī)模"].apply(func)

11、構(gòu)造新數(shù)據(jù)

我們針對(duì)最終清洗干凈的數(shù)據(jù),選取需要分析的字段,做一個(gè)數(shù)據(jù)存儲(chǔ)。

feature = ["公司名","崗位名","工作地點(diǎn)","工資水平","發(fā)布日期","學(xué)歷","公司類型","公司規(guī)模","行業(yè)","工作描述"]
final_df = job_info[feature]
final_df.to_excel(r"G:\8泰迪\python_project\51_job\詞云圖.xlsx",encoding="gbk",index=None)

關(guān)于“工作描述”字段的特殊處理

由于我們之后需要針對(duì)不同的崗位名做不同的詞云圖處理,并且是在tableau中做可視化展示,因此我們需要按照崗位名分類,求出不同崗位下各關(guān)鍵詞的詞頻統(tǒng)計(jì)。

import numpy as np
import pandas as pd
import re
import jieba
import warnings
warnings.filterwarnings("ignore")

df = pd.read_excel(r"G:\8泰迪\python_project\51_job\new_job_info1.xlsx",encoding="gbk")
df

def get_word_cloud(data=None, job_name=None):
    words = []
    describe = data['工作描述'][data['崗位名'] == job_name].str[1:-1]
    describe.dropna(inplace=True)
    [words.extend(i.split(',')) for i in describe]
    words = pd.Series(words)
    word_fre = words.value_counts()
    return word_fre

zz = ['數(shù)據(jù)分析', '算法', '大數(shù)據(jù)','開發(fā)工程師', '運(yùn)營(yíng)', '軟件工程','運(yùn)維', '數(shù)據(jù)庫(kù)','java',"測(cè)試"]
for i in zz:
    word_fre = get_word_cloud(data=df, job_name='{}'.format(i))
    word_fre = word_fre[1:].reset_index()[:100]
    word_fre["崗位名"] = pd.Series("{}".format(i),index=range(len(word_fre)))
    word_fre.to_csv(r"G:\8泰迪\python_project\51_job\詞云圖\bb.csv", mode='a',index=False, header=None,encoding="gbk")

tableau可視化展示

1、熱門城市的用人需求TOP10

如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏

2、熱門城市的崗位數(shù)量TOP10

如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏

4、熱門崗位的薪資待遇

如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏

關(guān)于如何讓Python爬取招聘網(wǎng)站數(shù)據(jù)并實(shí)現(xiàn)可視化交互大屏問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI