国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

前程無(wú)憂(yōu)崗位數(shù)據(jù)爬取+Tableau可視化分析

233jl / 2326人閱讀

摘要:實(shí)際上,前程無(wú)憂(yōu)招聘網(wǎng)站上與數(shù)據(jù)有關(guān)的只有幾百頁(yè),而我們爬取了頁(yè)的所有數(shù)據(jù),因此在后面進(jìn)行數(shù)據(jù)處理時(shí)需要把無(wú)關(guān)的數(shù)據(jù)剔除掉。

目錄

一、項(xiàng)目背景

二、數(shù)據(jù)爬取

1、相關(guān)庫(kù)的導(dǎo)入與說(shuō)明

2、獲取二級(jí)頁(yè)面鏈接

1)分析一級(jí)頁(yè)面url特征

2)構(gòu)建一級(jí)url庫(kù)

3)爬取所有二級(jí)url鏈接

3、獲取崗位信息并保存

三、數(shù)據(jù)清洗

1、數(shù)據(jù)讀取、去重、空值處理

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

2)數(shù)據(jù)去重與控制處理

2、“崗位名稱(chēng)”字段預(yù)處理

1)”崗位名稱(chēng)“字段預(yù)覽

2)構(gòu)建關(guān)鍵詞,篩選名稱(chēng)

3)崗位名稱(chēng)標(biāo)準(zhǔn)化處理

3、“崗位薪資”字段預(yù)處理

4、“公司規(guī)模”字段預(yù)處理

5、“職位信息”字段預(yù)處理

6、其它字段預(yù)處理

7、數(shù)據(jù)存儲(chǔ)

四、Tableau數(shù)據(jù)可視化展示

1、崗位數(shù)量城市分布?xì)馀輬D

2、熱門(mén)城市用人需求Top15

?3、用人需求Top15行業(yè)及其薪資情況

4、各類(lèi)型企業(yè)崗位需求樹(shù)狀分布圖

5、經(jīng)驗(yàn)學(xué)歷與薪資需求突出顯示表?

6、不同行業(yè)知識(shí)、技能要求詞云圖

1)傳統(tǒng)制造業(yè)

2) 計(jì)算機(jī)相關(guān)行業(yè)

3)服務(wù)行業(yè)?

6、崗位數(shù)量與薪資水平地理分布

7、可視化看板最終展示結(jié)果

五、源代碼

1、爬蟲(chóng)源代碼

2、數(shù)據(jù)預(yù)處理源碼


一、項(xiàng)目背景

????????隨著科技的不斷進(jìn)步與發(fā)展,數(shù)據(jù)呈現(xiàn)爆發(fā)式的增長(zhǎng),各行各業(yè)對(duì)于數(shù)據(jù)的依賴(lài)越來(lái)越強(qiáng),與數(shù)據(jù)打交道在所難免,而社會(huì)對(duì)于“數(shù)據(jù)”方面的人才需求也在不斷增大。因此了解當(dāng)下企業(yè)究竟需要招聘什么樣的人才?需要什么樣的技能?不管是對(duì)于在校生,還是對(duì)于求職者來(lái)說(shuō),都顯得十分必要。
? ? ? ? 對(duì)于一名小白來(lái)說(shuō),想要入門(mén)數(shù)據(jù)分析,首先要了解目前社會(huì)對(duì)于數(shù)據(jù)相關(guān)崗位的需求情況,基于這一問(wèn)題,本文針對(duì)前程無(wú)憂(yōu)招聘網(wǎng)站,利用python爬取了其全國(guó)范圍內(nèi)大數(shù)據(jù)、數(shù)據(jù)分析、數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)、人工智能等與數(shù)據(jù)相關(guān)的崗位招聘信息。并通過(guò)Tableau可視化工具分析比較了不同行業(yè)的崗位薪資、用人需求等情況;以及不同行業(yè)、崗位的知識(shí)、技能要求等。

? ? ? ? ?可視化分析效果圖示例:

二、數(shù)據(jù)爬取

  • 爬取字段:崗位名稱(chēng)、公司名稱(chēng)、薪資水平、工作經(jīng)驗(yàn)、學(xué)歷需求、工作地點(diǎn)、招聘人數(shù)、發(fā)布時(shí)間、公司類(lèi)型、公司規(guī)模、行業(yè)領(lǐng)域、福利待遇、職位信息;
  • 說(shuō)明:在前程無(wú)憂(yōu)招聘網(wǎng)站中,我們?cè)谒阉骺蛑休斎搿皵?shù)據(jù)”兩個(gè)字進(jìn)行搜索發(fā)現(xiàn),共有2000個(gè)一級(jí)頁(yè)面,其中每個(gè)頁(yè)面包含50條崗位信息,因此總共有約100000條招聘信息。當(dāng)點(diǎn)擊一級(jí)頁(yè)面中每個(gè)崗位信息時(shí),頁(yè)面會(huì)跳轉(zhuǎn)至相應(yīng)崗位的二級(jí)頁(yè)面,二級(jí)頁(yè)面中即包含我們所需要的全部字段信息;

????????一級(jí)頁(yè)面如下:

????????二級(jí)頁(yè)面如下:

  • 爬取思路:先針對(duì)一級(jí)頁(yè)面爬取所有崗位對(duì)應(yīng)的二級(jí)頁(yè)面鏈接,再根據(jù)二級(jí)頁(yè)面鏈接遍歷爬取相應(yīng)崗位信息;
  • 開(kāi)發(fā)環(huán)境:python3、Spyder

1、相關(guān)庫(kù)的導(dǎo)入與說(shuō)明

import jsonimport requestsimport pandas as pdfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom lxml import etreefrom selenium.webdriver import ChromeOptions

? ? ? ? 由于前程無(wú)憂(yōu)招聘網(wǎng)站的反爬機(jī)制較強(qiáng),采用動(dòng)態(tài)渲染+限制ip訪問(wèn)頻率等多層反爬,因此在獲取二級(jí)頁(yè)面鏈接時(shí)需借助json進(jìn)行解析,本文對(duì)于二級(jí)頁(yè)面崗位信息的獲取采用selenium模擬瀏覽器爬取,同時(shí)通過(guò)代理IP的方式,每隔一段時(shí)間換一次請(qǐng)求IP以免觸發(fā)網(wǎng)站反爬機(jī)制。?

2、獲取二級(jí)頁(yè)面鏈接

1)分析一級(jí)頁(yè)面url特征

# 第一頁(yè)URL的特征"https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,1.html?"# 第二頁(yè)URL的特征"https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,2.html?"# 第三頁(yè)URL的特征"https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,3.html?"

? ? ? ? 通過(guò)觀察不同頁(yè)面的URL可以發(fā)現(xiàn),不同頁(yè)面的URL鏈接只有“.html”前面的數(shù)字不同,該數(shù)字正好代表該頁(yè)的頁(yè)碼?,因此只需要構(gòu)造字符串拼接,然后通過(guò)for循環(huán)語(yǔ)句即可構(gòu)造自動(dòng)翻頁(yè)。

2)構(gòu)建一級(jí)url庫(kù)

url1 = []for i in range(2000):    url_pre = "https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,%s" % (1+i) #設(shè)置自動(dòng)翻頁(yè)       url_end = ".html?"    url_all = url_pre + url_end    url1.append(url_all)print("一級(jí)URL庫(kù)創(chuàng)建完畢")

3)爬取所有二級(jí)url鏈接

url2 = []j = 0for url in url1:    j += 1    re1 = requests.get(url , headers = headers,proxies= {"http":"tps131.kdlapi.com:15818"},timeout=(5,10))  #通過(guò)proxies設(shè)置代理ip    html1 = etree.HTML(re1.text)        divs = html1.xpath("http://script[@type = "text/javascript"]/text()")[0].replace("window.__SEARCH_RESULT__ = ","")        js = json.loads(divs)    for i in range(len(js["engine_jds"])):        if js["engine_jds"][i]["job_href"][0:22] == "https://jobs.51job.com":            url2.append(js["engine_jds"][i]["job_href"])        else:            print("url異常,棄用")  #剔除異常url    print("已爬取"+str(j)+"頁(yè)")print("成功爬取"+str(len(url2))+"條二級(jí)URL")

注意:爬取二級(jí)URL鏈接時(shí)發(fā)現(xiàn)并非爬取的所有鏈接都是規(guī)范的,會(huì)存在少部分異常URL,這會(huì)對(duì)后續(xù)崗位信息的爬取造成干擾,因此需要利用if條件語(yǔ)句對(duì)其進(jìn)行剔除。

3、獲取崗位信息并保存

option = ChromeOptions()option.add_experimental_option("excludeSwitches", ["enable-automation"])option.add_argument("--proxy-server=http://tps131.kdlapi.com:15818")  #設(shè)置代理ipdriver = webdriver.Chrome(options=option)for url in url2:    co = 1    while co == 1:        try:            driver.get(url)            wait = WebDriverWait(driver,10,0.5)            wait.until(EC.presence_of_element_located((By.ID,"topIndex")))        except:            driver.close()            driver = webdriver.Chrome(options=option)            co = 1        else:            co = 0    try:        福利待遇 = driver.find_elements_by_xpath("http://div[@class = "t1"]")[0].text         崗位名稱(chēng) = driver.find_element_by_xpath("http://div[@class = "cn"]/h1").text        薪資水平 = driver.find_element_by_xpath("http://div[@class = "cn"]/strong").text        職位信息 = driver.find_elements_by_xpath("http://div[@class = "bmsg job_msg inbox"]")[0].text        公司類(lèi)型 = driver.find_elements_by_xpath("http://div[@class = "com_tag"]/p")[0].text        公司規(guī)模 = driver.find_elements_by_xpath("http://div[@class = "com_tag"]/p")[1].text        公司領(lǐng)域 = driver.find_elements_by_xpath("http://div[@class = "com_tag"]/p")[2].text        公司名稱(chēng) = driver.find_element_by_xpath("http://div[@class = "com_msg"]/a/p").text        工作地點(diǎn) = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[0]        工作經(jīng)驗(yàn) = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[1]        學(xué)歷要求 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[2]        招聘人數(shù) = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[3]        發(fā)布時(shí)間 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[4]    except:        福利待遇 = "nan"         崗位名稱(chēng) = "nan"        薪資水平 = "nan"        職位信息 = "nan"        公司類(lèi)型 = "nan"        公司規(guī)模 = "nan"        公司領(lǐng)域 = "nan"        公司名稱(chēng) = "nan"        工作地點(diǎn) = "nan"        工作經(jīng)驗(yàn) = "nan"        學(xué)歷要求 = "nan"        招聘人數(shù) = "nan"        發(fā)布時(shí)間 = "nan"        print("信息提取異常,棄用")    finally:             info = {                "崗位名稱(chēng)" : 崗位名稱(chēng),            "公司名稱(chēng)" : 公司名稱(chēng),            "薪資水平" : 薪資水平,            "工作經(jīng)驗(yàn)" : 工作經(jīng)驗(yàn),            "學(xué)歷要求" : 學(xué)歷要求,            "工作地點(diǎn)" : 工作地點(diǎn),            "招聘人數(shù)" : 招聘人數(shù),            "發(fā)布時(shí)間" : 發(fā)布時(shí)間,            "公司類(lèi)型" : 公司類(lèi)型,            "公司規(guī)模" : 公司規(guī)模,            "公司領(lǐng)域" : 公司領(lǐng)域,            "福利待遇" : 福利待遇,            "職位信息" : 職位信息            }        jobs_info.append(info)df = pd.DataFrame(jobs_info)df.to_excel(r"E:/python爬蟲(chóng)/前程無(wú)憂(yōu)招聘信息.xlsx") 

? ? ? ? 在爬取并剔除異常數(shù)據(jù)之后,最終得到了90000多條完整的數(shù)據(jù)做分析,但經(jīng)過(guò)觀察發(fā)現(xiàn),所爬取的數(shù)據(jù)并非全都與“數(shù)據(jù)”崗位相關(guān)聯(lián)。實(shí)際上,前程無(wú)憂(yōu)招聘網(wǎng)站上與“數(shù)據(jù)”有關(guān)的只有幾百頁(yè),而我們爬取了2000頁(yè)的所有數(shù)據(jù),因此在后面進(jìn)行數(shù)據(jù)處理時(shí)需要把無(wú)關(guān)的數(shù)據(jù)剔除掉。在爬取前根據(jù)對(duì)代碼的測(cè)試發(fā)現(xiàn),有些崗位字段在進(jìn)行爬取時(shí)會(huì)出現(xiàn)錯(cuò)位,從而導(dǎo)致數(shù)據(jù)存儲(chǔ)失敗,為了不影響后面代碼的執(zhí)行,這里設(shè)置了“try-except”進(jìn)行異常處理,同時(shí)使用while循環(huán)語(yǔ)句在服務(wù)器出現(xiàn)請(qǐng)求失敗時(shí)關(guān)閉模擬瀏覽器并進(jìn)行重新請(qǐng)求。

三、數(shù)據(jù)清洗

1、數(shù)據(jù)讀取、去重、空值處理

????????在獲取了所需數(shù)據(jù)之后,可以看出數(shù)據(jù)較亂,并不利于我們進(jìn)行分析,因此在分析前需要對(duì)數(shù)據(jù)進(jìn)行預(yù)處理,得到規(guī)范格式的數(shù)據(jù)才可以用來(lái)最終做可視化數(shù)據(jù)展示。

? ? ? ? 獲取的數(shù)據(jù)截圖如下:

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

#導(dǎo)入相關(guān)庫(kù)import pandas as pdimport numpy as npimport jieba#讀取數(shù)據(jù)df = pd.read_excel(r"E:/python爬蟲(chóng)/前程無(wú)憂(yōu)招聘信息.xlsx",index_col=0)

2)數(shù)據(jù)去重與控制處理

  • 對(duì)于重復(fù)值的定義,我們認(rèn)為一個(gè)記錄的公司名稱(chēng)和崗位名稱(chēng)一致時(shí),即可看作是重復(fù)值。因此利用drop_duplicates()函數(shù)剔除所有公司名稱(chēng)和崗位名稱(chēng)相同的記錄并保留第一個(gè)記錄。
  • 對(duì)于空值處理,只刪除所有字段信息都為nan的記錄。
#去除重復(fù)數(shù)據(jù)df.drop_duplicates(subset=["公司名稱(chēng)","崗位名稱(chēng)"],inplace=True)#空值刪除df[df["公司名稱(chēng)"].isnull()]df.dropna(how="all",inplace=True)

2、“崗位名稱(chēng)”字段預(yù)處理

1)”崗位名稱(chēng)“字段預(yù)覽

? ? ? ? 首先我們對(duì)“崗位名稱(chēng)”的格式進(jìn)行調(diào)整,將其中所有大寫(xiě)英文字母統(tǒng)一轉(zhuǎn)換為小寫(xiě),例如將"Java"轉(zhuǎn)換為"java",然后對(duì)所有崗位做一個(gè)頻次統(tǒng)計(jì),統(tǒng)計(jì)結(jié)果發(fā)現(xiàn)“崗位名稱(chēng)”字段很雜亂,且存在很多與“數(shù)據(jù)”無(wú)關(guān)的崗位,因此要對(duì)數(shù)據(jù)做一個(gè)篩選。

df["崗位名稱(chēng)"] = df["崗位名稱(chēng)"].apply(lambda x:x.lower())counts = df["崗位名稱(chēng)"].value_counts() 

2)構(gòu)建關(guān)鍵詞,篩選名稱(chēng)

? ? ? ? 首先我們列出與“數(shù)據(jù)”崗位“有關(guān)的一系列關(guān)鍵詞,然后通過(guò)count()與for語(yǔ)句對(duì)所有記錄進(jìn)行統(tǒng)計(jì)判斷,如果包含任一關(guān)鍵詞則保留該記錄,如果不包含則刪除該字段。

#構(gòu)建目標(biāo)關(guān)鍵詞target_job = ["算法","開(kāi)發(fā)","分析","工程師","數(shù)據(jù)","運(yùn)營(yíng)","運(yùn)維","it","倉(cāng)庫(kù)","統(tǒng)計(jì)"]#篩選目標(biāo)數(shù)據(jù)index = [df["崗位名稱(chēng)"].str.count(i) for i in target_job]index = np.array(index).sum(axis=0) > 0job_info = df[index]

3)崗位名稱(chēng)標(biāo)準(zhǔn)化處理

? ? ? ? 基于前面對(duì)“崗位名稱(chēng)”字段的統(tǒng)計(jì)情況,我們定義了目標(biāo)崗位列表job_list,用來(lái)替換統(tǒng)一相近的崗位名稱(chēng),之后,我們將“數(shù)據(jù)專(zhuān)員”、“數(shù)據(jù)統(tǒng)計(jì)”統(tǒng)一歸為“數(shù)據(jù)分析”。

job_list = ["數(shù)據(jù)分析","數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)專(zhuān)員","數(shù)據(jù)挖掘","算法","大數(shù)據(jù)","開(kāi)發(fā)工程師","運(yùn)營(yíng)",            "軟件工程","前端開(kāi)發(fā)","深度學(xué)習(xí)","ai","數(shù)據(jù)庫(kù)","倉(cāng)庫(kù)管理","數(shù)據(jù)產(chǎn)品","客服",            "java",".net","andrio","人工智能","c++","數(shù)據(jù)管理","測(cè)試","運(yùn)維","數(shù)據(jù)工程師"]job_list = np.array(job_list)def Rename(x,job_list=job_list):    index = [i in x for i in job_list]    if sum(index) > 0:        return job_list[index][0]    else:        return xjob_info["崗位名稱(chēng)"] = job_info["崗位名稱(chēng)"].apply(Rename)job_info["崗位名稱(chēng)"] = job_info["崗位名稱(chēng)"].apply(lambda x:x.replace("數(shù)據(jù)專(zhuān)員","數(shù)據(jù)分析"))job_info["崗位名稱(chēng)"] = job_info["崗位名稱(chēng)"].apply(lambda x:x.replace("數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)分析"))

? ? ? ? 統(tǒng)一之后的“崗位名稱(chēng)”如下圖所示:

?

3、“崗位薪資”字段預(yù)處理

? ? ? ? 對(duì)于“崗位薪資”字段的處理,重點(diǎn)在于對(duì)其單位格式轉(zhuǎn)換,在簡(jiǎn)單觀察該字段后發(fā)現(xiàn),其存在“萬(wàn)/年”、“萬(wàn)/月”、“千/月”等不同單位,因此需要對(duì)其做一個(gè)統(tǒng)一換算,將數(shù)據(jù)格式統(tǒng)一轉(zhuǎn)換為“元/月”,并根據(jù)最高工資與最低工資求出平均值。

job_info["崗位薪資"].value_counts()#剔除異常數(shù)據(jù)index1 = job_info["崗位薪資"].str[-1].isin(["年","月"])index2 = job_info["崗位薪資"].str[-3].isin(["萬(wàn)","千"])job_info = job_info[index1 & index2]#計(jì)算平均工資job_info["平均薪資"] = job_info["崗位薪資"].astype(str).apply(lambda x:np.array(x[:-3].split("-"),dtype=float))job_info["平均薪資"] = job_info["平均薪資"].apply(lambda x:np.mean(x))#統(tǒng)一工資單位job_info["單位"] = job_info["崗位薪資"].apply(lambda x:x[-3:])def con_unit(x):    if x["單位"] == "萬(wàn)/月":        z = x["平均薪資"]*10000    elif x["單位"] == "千/月":        z = x["平均薪資"]*1000    elif x["單位"] == "萬(wàn)/年":        z = x["平均薪資"]/12*10000    return int(z)job_info["平均薪資"] = job_info.apply(con_unit,axis=1)job_info["單位"] = "元/月"

說(shuō)明:首先我們對(duì)該字段進(jìn)行統(tǒng)計(jì)預(yù)覽,之后做一個(gè)數(shù)據(jù)篩選剔除異常單位與空值記錄,再計(jì)算出每個(gè)字段的平均工資,接著定義一個(gè)函數(shù),將格式換算為“元/月”,得到最終的“平均薪資”字段。

4、“公司規(guī)模”字段預(yù)處理

? ? ? ? 對(duì)于“公司規(guī)模”字段的處理較簡(jiǎn)單,只需要定義一個(gè)if條件語(yǔ)句將其格式做一個(gè)轉(zhuǎn)換即可。

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.nanjob_info["公司規(guī)模"] = job_info["公司規(guī)模"].apply(func)

5、“職位信息”字段預(yù)處理

job_info["職位信息"] = job_info["職位信息"].apply(lambda x:x.split("職能類(lèi)別")[0])with open(r"E:/python爬蟲(chóng)/數(shù)據(jù)處理/停用詞表.txt","r",encoding = "utf8") as f:    stopword = f.read()stopword = stopword.split()#對(duì)“職業(yè)信息”字段進(jìn)行簡(jiǎn)單處理,去除無(wú)意義的文字,構(gòu)造jieba分詞job_info["職位信息"] = job_info["職位信息"].apply(lambda x:x.lower()).apply(lambda x:"".join(x)).apply(lambda x:x.strip()).apply(jieba.lcut).apply(lambda x:[i for i in x if i not in stopword])#按照行業(yè)進(jìn)行分類(lèi),求出每一個(gè)行業(yè)下各關(guān)鍵詞的詞頻統(tǒng)計(jì),以便于后期做詞云圖cons = job_info["公司領(lǐng)域"].value_counts()industries = pd.DataFrame(cons.index,columns=["行業(yè)領(lǐng)域"])industry = pd.DataFrame(columns=["分詞明細(xì)","行業(yè)領(lǐng)域"])for i in industries["行業(yè)領(lǐng)域"]:    words = []    word = job_info["職位信息"][job_info["公司領(lǐng)域"] == i]    word.dropna(inplace=True)    [words.extend(str(z).strip("/"[]").split("/", /"")) for z in word]    df1 = pd.DataFrame({"分詞明細(xì)":words,                        "行業(yè)領(lǐng)域":i})    industry = industry.append(df1,ignore_index=True)industry = industry[industry["分詞明細(xì)"] != "http://n"]industry = industry[industry["分詞明細(xì)"] != ""]#剔除詞頻小于300的關(guān)鍵詞count = pd.DataFrame(industry["分詞明細(xì)"].value_counts())lst = list(count[count["分詞明細(xì)"] >=300].index)industry = industry[industry["分詞明細(xì)"].isin(lst)]#數(shù)據(jù)存儲(chǔ)industry.to_excel(r"E:/python爬蟲(chóng)/數(shù)據(jù)處理/詞云.xlsx")   

6、其它字段預(yù)處理

  • “工作地點(diǎn)”字段:該字段有”市-區(qū)“和”市“兩種格式,如”廣州-天河“與”廣州“,因此需要統(tǒng)一轉(zhuǎn)換為”市“的格式;
  • “公司領(lǐng)域”字段:每個(gè)公司的行業(yè)字段可能會(huì)有多個(gè)行業(yè)標(biāo)簽,我們默認(rèn)以第一個(gè)作為改公司的行業(yè)標(biāo)簽;
  • “招聘人數(shù)”字段:由于某些公司崗位沒(méi)有具體招聘人數(shù),因此我們默認(rèn)以最低需求為標(biāo)準(zhǔn),將“招若干人”改為“招1人”,以便于后面統(tǒng)計(jì)分析;
  • 其它字段:對(duì)于其他幾個(gè)字段格式只存在一些字符串空格問(wèn)題,因此只需要對(duì)其進(jìn)行去除空格即可。
#工作地點(diǎn)字段處理job_info["工作地點(diǎn)"] = job_info["工作地點(diǎn)"].apply(lambda x:x.split("-")[0])#公司領(lǐng)域字段處理job_info["公司領(lǐng)域"] = job_info["公司領(lǐng)域"].apply(lambda x:x.split("/")[0])a = job_info["公司領(lǐng)域"].value_counts()#招聘人數(shù)字段處理job_info["招聘人數(shù)"] = job_info["招聘人數(shù)"].apply(lambda x:x.replace("若干","1").strip()[1:-1])#工作經(jīng)驗(yàn)與學(xué)歷要求字段處理job_info["工作經(jīng)驗(yàn)"] = job_info["工作經(jīng)驗(yàn)"].apply(lambda x:x.replace("無(wú)需","1年以下").strip()[:-2])job_info["學(xué)歷需求"] = job_info["學(xué)歷需求"].apply(lambda x:x.split()[0])#公司福利字段處理job_info["公司福利"] = job_info["公司福利"].apply(lambda x:str(x).split())

7、數(shù)據(jù)存儲(chǔ)

? ? ? ? 我們針對(duì)清洗干凈后的數(shù)據(jù)另存為一個(gè)文檔,對(duì)源數(shù)據(jù)不做修改。

job_info.to_excel(r"E:/python爬蟲(chóng)/前程無(wú)憂(yōu)(已清洗).xlsx")

四、Tableau數(shù)據(jù)可視化展示

1、崗位數(shù)量城市分布?xì)馀輬D

結(jié)論分析:從氣泡圖中可以看出,“數(shù)據(jù)”相關(guān)崗位數(shù)量較高的城市有:上海、深圳、廣州、北京、杭州、武漢等。

2、熱門(mén)城市用人需求Top15

結(jié)論分析:通過(guò)條形圖可以看出,“數(shù)據(jù)”相關(guān)崗位用人需求達(dá)1000人以上的城市有15個(gè),需求由高到低依次為:上海、深圳、廣州、北京、武漢、杭州、成都、南京、蘇州、無(wú)錫、西安、長(zhǎng)沙、鄭州、重慶。其中上海用人需求高達(dá)10000人。

?3、用人需求Top15行業(yè)及其薪資情況

結(jié)論分析:從不同行業(yè)的用人需求與薪資對(duì)比可知,用人需求排名前4的行業(yè)分別:計(jì)算機(jī)軟件、互聯(lián)網(wǎng)、電子技術(shù)、計(jì)算機(jī)服務(wù);平均薪資排名前4的行業(yè)分別為:互聯(lián)網(wǎng)、計(jì)算機(jī)軟件、通信、專(zhuān)業(yè)服務(wù)。可以發(fā)現(xiàn),“數(shù)據(jù)”相關(guān)崗位在計(jì)算機(jī)領(lǐng)域需求大,薪資高,前景好。

4、各類(lèi)型企業(yè)崗位需求樹(shù)狀分布圖

結(jié)論分析:在發(fā)布的眾多崗位需求信息中,以民營(yíng)公司為主,其崗位數(shù)量、用人需求極高,但薪資待遇一般,而上市公司的崗位數(shù)量一般,但薪資待遇好。

5、經(jīng)驗(yàn)學(xué)歷與薪資需求突出顯示表?

????????注:顏色深淺表示薪資高低,數(shù)字表示招聘人數(shù)

結(jié)論分析:根據(jù)突出顯示表可以發(fā)現(xiàn),在學(xué)歷要求方面,大專(zhuān)與本科生需求量較大;經(jīng)驗(yàn)要求方面,3年以下相關(guān)經(jīng)驗(yàn)的崗位占大多數(shù),而薪資方面,學(xué)歷越高,經(jīng)驗(yàn)越豐富則薪資越高。因此可以判斷數(shù)據(jù)分析行業(yè)還是一個(gè)較新興的行業(yè),目前行業(yè)的基礎(chǔ)崗位較多,且具有豐富經(jīng)驗(yàn)的專(zhuān)家較少。

6、不同行業(yè)知識(shí)、技能要求詞云圖

1)傳統(tǒng)制造業(yè)

2) 計(jì)算機(jī)相關(guān)行業(yè)

3)服務(wù)行業(yè)

?結(jié)論分析:上圖通過(guò)列舉了傳統(tǒng)制造業(yè)、計(jì)算機(jī)相關(guān)行業(yè)以及服務(wù)業(yè)三個(gè)行業(yè)進(jìn)行對(duì)比分析,三個(gè)行業(yè)對(duì)于“數(shù)據(jù)”相關(guān)崗位工作要求的共同點(diǎn)都是注重相關(guān)的行業(yè)經(jīng)驗(yàn)及數(shù)據(jù)處理等能力,而計(jì)算機(jī)相關(guān)行業(yè)對(duì)于技術(shù)如開(kāi)發(fā)、數(shù)據(jù)庫(kù)、系統(tǒng)維護(hù)等編程能力要求較高,傳統(tǒng)制造業(yè)和服務(wù)行業(yè)則更側(cè)重于業(yè)務(wù)分析、管理、團(tuán)隊(duì)合作綜合型能力等。

6、崗位數(shù)量與薪資水平地理分布

7、可視化看板最終展示結(jié)果

?

五、源代碼

1、爬蟲(chóng)源代碼

import jsonimport requestsimport pandas as pdfrom lxml import etreefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver import ChromeOptionsfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECurl1 = []url2 = []jobs_info = []for i in range(2000):    url_pre = "https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,%s" % (1+i)    #頁(yè)面跳轉(zhuǎn)    url_end = ".html?"    url_all = url_pre + url_end    url1.append(url_all)print("一級(jí)URL庫(kù)創(chuàng)建完畢")#從json中提取數(shù)據(jù)并加載headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36",           "Connection": "close",           "Host": "search.51job.com"}j = 0for url in url1:    j += 1    re1 = requests.get(url , headers = headers,proxies= {"http":"tps131.kdlapi.com:15818"},timeout=(5,10))    html1 = etree.HTML(re1.text)        divs = html1.xpath("http://script[@type = "text/javascript"]/text()")[0].replace("window.__SEARCH_RESULT__ = ","")        js = json.loads(divs)    for i in range(len(js["engine_jds"])):        if js["engine_jds"][i]["job_href"][0:22] == "https://jobs.51job.com":            url2.append(js["engine_jds"][i]["job_href"])        else:            print("url異常,棄用")    print("已解析"+str(j)+"頁(yè)")print("成功提取"+str(len(url2))+"條二級(jí)URL")#爬取崗位數(shù)據(jù)option = ChromeOptions()option.add_experimental_option("excludeSwitches", ["enable-automation"])option.add_argument("--proxy-server=http://tps131.kdlapi.com:15818") driver = webdriver.Chrome(options=option)for url in url2:    co = 1    while co == 1:        try:             #設(shè)置IP代理            driver.get(url)            wait = WebDriverWait(driver,10,0.5)            wait.until(EC.presence_of_element_located((By.ID,"topIndex")))        except:            driver.close()            driver = webdriver.Chrome(options=option)            co = 1        else:            co = 0    try:        福利待遇 = driver.find_elements_by_xpath("http://div[@class = "t1"]")[0].text         崗位名稱(chēng) = driver.find_element_by_xpath("http://div[@class = "cn"]/h1").text        薪資水平 = driver.find_element_by_xpath("http://div[@class = "cn"]/strong").text        職位信息 = driver.find_elements_by_xpath("http://div[@class = "bmsg job_msg inbox"]")[0].text        公司類(lèi)型 = driver.find_elements_by_xpath("http://div[@class = "com_tag"]/p")[0].text        公司規(guī)模 = driver.find_elements_by_xpath("http://div[@class = "com_tag"]/p")[1].text        公司領(lǐng)域 = driver.find_elements_by_xpath("http://div[@class = "com_tag"]/p")[2].text        公司名稱(chēng) = driver.find_element_by_xpath("http://div[@class = "com_msg"]/a/p").text        工作地點(diǎn) = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[0]        工作經(jīng)驗(yàn) = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[1]        學(xué)歷要求 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[2]        招聘人數(shù) = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[3]        發(fā)布時(shí)間 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[4]    except:        福利待遇 = "nan"         崗位名稱(chēng) = "nan"        薪資水平 = "nan"        職位信息 = "nan"        公司類(lèi)型 = "nan"        公司規(guī)模 = "nan"        公司領(lǐng)域 = "nan"        公司名稱(chēng) = "nan"        工作地點(diǎn) = "nan"        工作經(jīng)驗(yàn) = "nan"        學(xué)歷要求 = "nan"        招聘人數(shù) = "nan"        發(fā)布時(shí)間 = "nan"        print("信息提取異常,棄用")    finally:             info = {                "崗位名稱(chēng)" : 崗位名稱(chēng),            "公司名稱(chēng)" : 公司名稱(chēng),            "薪資水平" : 薪資水平,            "工作經(jīng)驗(yàn)" : 工作經(jīng)驗(yàn),            "學(xué)歷要求" : 學(xué)歷要求,            "工作地點(diǎn)" : 工作地點(diǎn),            "招聘人數(shù)" : 招聘人數(shù),            "發(fā)布時(shí)間" : 發(fā)布時(shí)間,            "公司類(lèi)型" : 公司類(lèi)型,            "公司規(guī)模" : 公司規(guī)模,            "公司領(lǐng)域" : 公司領(lǐng)域,            "福利待遇" : 福利待遇,            "職位信息" : 職位信息            }        jobs_info.append(info)df = pd.DataFrame(jobs_info)df.to_excel(r"E:/python爬蟲(chóng)/前程無(wú)憂(yōu)招聘信息.xlsx") 

2、數(shù)據(jù)預(yù)處理源碼

import pandas as pdimport numpy as npimport jieba#數(shù)據(jù)讀取df = pd.read_excel(r"E:/python爬蟲(chóng)/前程無(wú)憂(yōu)招聘信息.xlsx",index_col=0)#數(shù)據(jù)去重與空值處理df.drop_duplicates(subset=["公司名稱(chēng)","崗位名稱(chēng)"],inplace=True)df[df["招聘人數(shù)"].isnull()]df.dropna(how="all",inplace=True)#崗位名稱(chēng)字段處理df["崗位名稱(chēng)"] = df["崗位名稱(chēng)"].apply(lambda x:x.lower())counts = df["崗位名稱(chēng)"].value_counts() target_job = ["算法","開(kāi)發(fā)","分析","工程師","數(shù)據(jù)","運(yùn)營(yíng)","運(yùn)維","it","倉(cāng)庫(kù)","統(tǒng)計(jì)"]index = [df["崗位名稱(chēng)"].str.count(i) for i in target_job]index = np.array(index).sum(axis=0) > 0job_info = df[index]job_list = ["數(shù)據(jù)分析","數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)專(zhuān)員","數(shù)據(jù)挖掘","算法","大數(shù)據(jù)","開(kāi)發(fā)工程師",            "運(yùn)營(yíng)","軟件工程","前端開(kāi)發(fā)","深度學(xué)習(xí)","ai","數(shù)據(jù)庫(kù)","倉(cāng)庫(kù)管理","數(shù)據(jù)產(chǎn)品",            "客服","java",".net","andrio","人工智能","c++","數(shù)據(jù)管理","測(cè)試","運(yùn)維","數(shù)據(jù)工程師"]job_list = np.array(job_list)def Rename(x,job_list=job_list):    index = [i in x for i in job_list]    if sum(index) > 0:        return job_list[index][0]    else:        return xjob_info["崗位名稱(chēng)"] = job_info["崗位名稱(chēng)"].apply(Rename)job_info["崗位名稱(chēng)"] = job_info["崗位名稱(chēng)"].apply(lambda x:x.replace("數(shù)據(jù)專(zhuān)員","數(shù)據(jù)分析"))job_info["崗位名稱(chēng)"] = job_info["崗位名稱(chēng)"].apply(lambda x:x.replace("數(shù)據(jù)統(tǒng)計(jì)","數(shù)據(jù)分析"))#崗位薪資字段處理index1 = job_info["崗位薪資"].str[-1].isin(["年","月"])index2 = job_info["崗位薪資"].str[-3].isin(["萬(wàn)","千"])job_info = job_info[index1 & index2]job_info["平均薪資"] = job_info["崗位薪資"].astype(str).apply(lambda x:np.array(x[:-3].split("-"),dtype=float))job_info["平均薪資"] = job_info["平均薪資"].apply(lambda x:np.mean(x))#統(tǒng)一工資單位job_info["單位"] = job_info["崗位薪資"].apply(lambda x:x[-3:])job_info["公司領(lǐng)域"].value_counts()def con_unit(x):    if x["單位"] == "萬(wàn)/月":        z = x["平均薪資"]*10000    elif x["單位"] == "千/月":        z = x["平均薪資"]*1000    elif x["單位"] == "萬(wàn)/年":        z = x["平均薪資"]/12*10000    return int(z)job_info["平均薪資"] = job_info.apply(con_unit,axis=1)job_info["單位"] = "元/月"#工作地點(diǎn)字段處理job_info["工作地點(diǎn)"] = job_info["工作地點(diǎn)"].apply(lambda x:x.split("-")[0])#公司領(lǐng)域字段處理job_info["公司領(lǐng)域"] = job_info["公司領(lǐng)域"].apply(lambda x:x.split("/")[0])#招聘人數(shù)字段處理job_info["招聘人數(shù)"] = job_info["招聘人數(shù)"].apply(lambda x:x.replace("若干","1").strip()[1:-1])#工作經(jīng)驗(yàn)與學(xué)歷要求字段處理job_info["工作經(jīng)驗(yàn)"] = job_info["工作經(jīng)驗(yàn)"].apply(lambda x:x.replace("無(wú)需","1年以下").strip()[:-2])job_info["學(xué)歷需求"] = job_info["學(xué)歷需求"].apply(lambda x:x.split()[0])#公司規(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.nanjob_info["公司規(guī)模"] = job_info["公司規(guī)模"].apply(func)#公司福利字段處理job_info["公司福利"] = job_info["公司福利"].apply(lambda x:str(x).split())#職位信息字段處理job_info["職位信息"] = job_info["職位信息"].apply(lambda x:x.split("職能類(lèi)別")[0])with open(r"E:/C++/停用詞表.txt","r",encoding = "utf8") as f:    stopword = f.read()stopword = stopword.split()job_info["職位信息"] = job_info["職位信息"].apply(lambda x:x.lower()).apply(lambda x:"".join(x)).apply(lambda x:x.strip()).apply(jieba.lcut).apply(lambda x:[i for i in x if i not in stopword])cons = job_info["公司領(lǐng)域"].value_counts()industries = pd.DataFrame(cons.index,columns=["行業(yè)領(lǐng)域"])industry = pd.DataFrame(columns=["分詞明細(xì)","行業(yè)領(lǐng)域"])for i in industries["行業(yè)領(lǐng)域"]:    words = []    word = job_info["職位信息"][job_info["公司領(lǐng)域"] == i]    word.dropna(inplace=True)    [words.extend(str(z).strip("/"[]").split("/", /"")) for z in word]    df1 = pd.DataFrame({"分詞明細(xì)":words,                        "行業(yè)領(lǐng)域":i})    industry = industry.append(df1,ignore_index=True)industry = industry[industry["分詞明細(xì)"] != "http://n"]industry = industry[industry["分詞明細(xì)"] != ""]count = pd.DataFrame(industry["分詞明細(xì)"].value_counts())lst = list(count[count["分詞明細(xì)"] >=300].index)industry = industry[industry["分詞明細(xì)"].isin(lst)]#數(shù)據(jù)存儲(chǔ)industry.to_excel(r"E:/python爬蟲(chóng)/數(shù)據(jù)預(yù)處理/詞云.xlsx")       job_info.to_excel(r"E:/python爬蟲(chóng)/數(shù)據(jù)預(yù)處理/前程無(wú)憂(yōu)(已清洗).xlsx")

?

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/121420.html

相關(guān)文章

  • 小李飛刀:ppppppython是需要好好學(xué)習(xí)的

    摘要:直接抄其中一份的結(jié)論吧各地區(qū)招聘公司數(shù)量和平均待遇。可以看出不論是招聘公司的數(shù)據(jù)還是平均待遇水平主要都是北上廣深杭州占優(yōu)勢(shì)。但事實(shí)證明,總是要有一些代價(jià)的。要學(xué)會(huì)看報(bào)錯(cuò)信息。函數(shù)定義結(jié)束后需要按兩次回車(chē)重新回到提示符下。 又是寫(xiě)在前面的亂七八糟 持續(xù)學(xué)習(xí)的第三天了,持續(xù)學(xué)習(xí)是一個(gè)不容易培養(yǎng)的好習(xí)慣,但是堅(jiān)持就是勝利嘛~昨天因?yàn)橐稽c(diǎn)點(diǎn)事情,所以沒(méi)能學(xué)習(xí)很長(zhǎng)時(shí)間,今天要補(bǔ)回來(lái)。周末要搬家,...

    Simon 評(píng)論0 收藏0
  • node.js 爬取招聘信息分析各職業(yè)錢(qián)途(爬蟲(chóng)+動(dòng)態(tài)IP代理+數(shù)據(jù)視化分析

    摘要:成功爬取了拉鉤網(wǎng)上多個(gè)招聘崗位的具體信息后,數(shù)據(jù)可視化并得出分析結(jié)果如下從整體看,北上廣深杭這五個(gè)城市前端工程師招聘崗位,北京是遙遙領(lǐng)先,是深圳的兩倍,是廣州的三倍,其次到上海,深圳,杭州,廣州居末。 前前言 本文首發(fā)于 github blog 不想看爬蟲(chóng)過(guò)程只想看職位錢(qián)途數(shù)據(jù)分析請(qǐng)看這里:前端招聘崗位分析C++招聘崗位分析JAVA招聘崗位分析PHP招聘崗位分析Python招聘崗位分析...

    546669204 評(píng)論0 收藏0
  • 拉勾數(shù)據(jù)崗位和熱門(mén)編程語(yǔ)言現(xiàn)狀分析

    摘要:另外數(shù)學(xué)成為了一個(gè)關(guān)鍵詞,編程語(yǔ)言主要是等,運(yùn)營(yíng)也出現(xiàn)在詞云中說(shuō)明數(shù)據(jù)分析師也需要有運(yùn)營(yíng)能力。 功能點(diǎn) 爬取數(shù)據(jù) 所有公司數(shù)據(jù),名稱(chēng)簡(jiǎn)寫(xiě),城市,行業(yè),職位數(shù)量,人數(shù)范圍,標(biāo)簽,介紹,融資階段,平均工資 github2016年度最受歡迎編程語(yǔ)言相應(yīng)年數(shù)薪水,城市,學(xué)歷要求,公司融資階段,公司行業(yè) 大數(shù)據(jù)行業(yè)五大崗位相應(yīng)年數(shù)薪水,城市,學(xué)歷要求,公司融資階段,公司行業(yè),崗位要求 編程語(yǔ)...

    atinosun 評(píng)論0 收藏0
  • EDG奪冠,Python分析一波B站評(píng)論,總結(jié):EDG,nb

    摘要:填寫(xiě)自己對(duì)應(yīng)的網(wǎng)頁(yè)更改相應(yīng)數(shù)據(jù)的編碼格式遇到請(qǐng)求掛起當(dāng)前任務(wù),等操作完成執(zhí)行之后的代碼,當(dāng)協(xié)程掛起時(shí),事件循環(huán)可以去執(zhí)行其他任務(wù)。 前言 2012,一個(gè)卡牌,一個(gè)雷...

    seasonley 評(píng)論0 收藏0
  • 如何用Python進(jìn)行數(shù)據(jù)分析

    摘要:編程基礎(chǔ)要學(xué)習(xí)如何用進(jìn)行數(shù)據(jù)分析,數(shù)據(jù)分析師建議第一步是要了解一些的編程基礎(chǔ),知道的數(shù)據(jù)結(jié)構(gòu),什么是向量列表數(shù)組字典等等了解的各種函數(shù)及模塊。數(shù)據(jù)分析師認(rèn)為數(shù)據(jù)分析有的工作都在處理數(shù)據(jù)。 showImg(https://segmentfault.com/img/bVbnbZo?w=1024&h=653); 本文為CDA數(shù)據(jù)分析研究院原創(chuàng)作品,轉(zhuǎn)載需授權(quán) 1.為什么選擇Python進(jìn)行數(shù)...

    lifefriend_007 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<