摘要:實際上,前程無憂招聘網(wǎng)站上與數(shù)據(jù)有關(guān)的只有幾百頁,而我們爬取了頁的所有數(shù)據(jù),因此在后面進(jìn)行數(shù)據(jù)處理時需要把無關(guān)的數(shù)據(jù)剔除掉。
目錄
1)相關(guān)庫導(dǎo)入及數(shù)據(jù)讀取
????????隨著科技的不斷進(jìn)步與發(fā)展,數(shù)據(jù)呈現(xiàn)爆發(fā)式的增長,各行各業(yè)對于數(shù)據(jù)的依賴越來越強(qiáng),與數(shù)據(jù)打交道在所難免,而社會對于“數(shù)據(jù)”方面的人才需求也在不斷增大。因此了解當(dāng)下企業(yè)究竟需要招聘什么樣的人才?需要什么樣的技能?不管是對于在校生,還是對于求職者來說,都顯得十分必要。
? ? ? ? 對于一名小白來說,想要入門數(shù)據(jù)分析,首先要了解目前社會對于數(shù)據(jù)相關(guān)崗位的需求情況,基于這一問題,本文針對前程無憂招聘網(wǎng)站,利用python爬取了其全國范圍內(nèi)大數(shù)據(jù)、數(shù)據(jù)分析、數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)、人工智能等與數(shù)據(jù)相關(guān)的崗位招聘信息。并通過Tableau可視化工具分析比較了不同行業(yè)的崗位薪資、用人需求等情況;以及不同行業(yè)、崗位的知識、技能要求等。
? ? ? ? ?可視化分析效果圖示例:
????????一級頁面如下:
????????二級頁面如下:
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ǎng)站的反爬機(jī)制較強(qiáng),采用動態(tài)渲染+限制ip訪問頻率等多層反爬,因此在獲取二級頁面鏈接時需借助json進(jìn)行解析,本文對于二級頁面崗位信息的獲取采用selenium模擬瀏覽器爬取,同時通過代理IP的方式,每隔一段時間換一次請求IP以免觸發(fā)網(wǎng)站反爬機(jī)制。?
# 第一頁URL的特征"https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,1.html?"# 第二頁URL的特征"https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,2.html?"# 第三頁URL的特征"https://search.51job.com/list/000000,000000,0000,00,9,99,數(shù)據(jù),2,3.html?"
? ? ? ? 通過觀察不同頁面的URL可以發(fā)現(xiàn),不同頁面的URL鏈接只有“.html”前面的數(shù)字不同,該數(shù)字正好代表該頁的頁碼?,因此只需要構(gòu)造字符串拼接,然后通過for循環(huán)語句即可構(gòu)造自動翻頁。
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è)置自動翻頁 url_end = ".html?" url_all = url_pre + url_end url1.append(url_all)print("一級URL庫創(chuàng)建完畢")
url2 = []j = 0for url in url1: j += 1 re1 = requests.get(url , headers = headers,proxies= {"http":"tps131.kdlapi.com:15818"},timeout=(5,10)) #通過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)+"頁")print("成功爬取"+str(len(url2))+"條二級URL")
注意:爬取二級URL鏈接時發(fā)現(xiàn)并非爬取的所有鏈接都是規(guī)范的,會存在少部分異常URL,這會對后續(xù)崗位信息的爬取造成干擾,因此需要利用if條件語句對其進(jìn)行剔除。
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 崗位名稱 = 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 公司類型 = 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 公司名稱 = driver.find_element_by_xpath("http://div[@class = "com_msg"]/a/p").text 工作地點 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[0] 工作經(jīng)驗 = 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ā)布時間 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[4] except: 福利待遇 = "nan" 崗位名稱 = "nan" 薪資水平 = "nan" 職位信息 = "nan" 公司類型 = "nan" 公司規(guī)模 = "nan" 公司領(lǐng)域 = "nan" 公司名稱 = "nan" 工作地點 = "nan" 工作經(jīng)驗 = "nan" 學(xué)歷要求 = "nan" 招聘人數(shù) = "nan" 發(fā)布時間 = "nan" print("信息提取異常,棄用") finally: info = { "崗位名稱" : 崗位名稱, "公司名稱" : 公司名稱, "薪資水平" : 薪資水平, "工作經(jīng)驗" : 工作經(jīng)驗, "學(xué)歷要求" : 學(xué)歷要求, "工作地點" : 工作地點, "招聘人數(shù)" : 招聘人數(shù), "發(fā)布時間" : 發(fā)布時間, "公司類型" : 公司類型, "公司規(guī)模" : 公司規(guī)模, "公司領(lǐng)域" : 公司領(lǐng)域, "福利待遇" : 福利待遇, "職位信息" : 職位信息 } jobs_info.append(info)df = pd.DataFrame(jobs_info)df.to_excel(r"E:/python爬蟲/前程無憂招聘信息.xlsx")
? ? ? ? 在爬取并剔除異常數(shù)據(jù)之后,最終得到了90000多條完整的數(shù)據(jù)做分析,但經(jīng)過觀察發(fā)現(xiàn),所爬取的數(shù)據(jù)并非全都與“數(shù)據(jù)”崗位相關(guān)聯(lián)。實際上,前程無憂招聘網(wǎng)站上與“數(shù)據(jù)”有關(guān)的只有幾百頁,而我們爬取了2000頁的所有數(shù)據(jù),因此在后面進(jìn)行數(shù)據(jù)處理時需要把無關(guān)的數(shù)據(jù)剔除掉。在爬取前根據(jù)對代碼的測試發(fā)現(xiàn),有些崗位字段在進(jìn)行爬取時會出現(xiàn)錯位,從而導(dǎo)致數(shù)據(jù)存儲失敗,為了不影響后面代碼的執(zhí)行,這里設(shè)置了“try-except”進(jìn)行異常處理,同時使用while循環(huán)語句在服務(wù)器出現(xiàn)請求失敗時關(guān)閉模擬瀏覽器并進(jìn)行重新請求。
????????在獲取了所需數(shù)據(jù)之后,可以看出數(shù)據(jù)較亂,并不利于我們進(jìn)行分析,因此在分析前需要對數(shù)據(jù)進(jìn)行預(yù)處理,得到規(guī)范格式的數(shù)據(jù)才可以用來最終做可視化數(shù)據(jù)展示。
? ? ? ? 獲取的數(shù)據(jù)截圖如下:
#導(dǎo)入相關(guān)庫import pandas as pdimport numpy as npimport jieba#讀取數(shù)據(jù)df = pd.read_excel(r"E:/python爬蟲/前程無憂招聘信息.xlsx",index_col=0)
#去除重復(fù)數(shù)據(jù)df.drop_duplicates(subset=["公司名稱","崗位名稱"],inplace=True)#空值刪除df[df["公司名稱"].isnull()]df.dropna(how="all",inplace=True)
? ? ? ? 首先我們對“崗位名稱”的格式進(jìn)行調(diào)整,將其中所有大寫英文字母統(tǒng)一轉(zhuǎn)換為小寫,例如將"Java"轉(zhuǎn)換為"java",然后對所有崗位做一個頻次統(tǒng)計,統(tǒng)計結(jié)果發(fā)現(xiàn)“崗位名稱”字段很雜亂,且存在很多與“數(shù)據(jù)”無關(guān)的崗位,因此要對數(shù)據(jù)做一個篩選。
df["崗位名稱"] = df["崗位名稱"].apply(lambda x:x.lower())counts = df["崗位名稱"].value_counts()
? ? ? ? 首先我們列出與“數(shù)據(jù)”崗位“有關(guān)的一系列關(guān)鍵詞,然后通過count()與for語句對所有記錄進(jìn)行統(tǒng)計判斷,如果包含任一關(guān)鍵詞則保留該記錄,如果不包含則刪除該字段。
#構(gòu)建目標(biāo)關(guān)鍵詞target_job = ["算法","開發(fā)","分析","工程師","數(shù)據(jù)","運營","運維","it","倉庫","統(tǒng)計"]#篩選目標(biāo)數(shù)據(jù)index = [df["崗位名稱"].str.count(i) for i in target_job]index = np.array(index).sum(axis=0) > 0job_info = df[index]
? ? ? ? 基于前面對“崗位名稱”字段的統(tǒng)計情況,我們定義了目標(biāo)崗位列表job_list,用來替換統(tǒng)一相近的崗位名稱,之后,我們將“數(shù)據(jù)專員”、“數(shù)據(jù)統(tǒng)計”統(tǒng)一歸為“數(shù)據(jù)分析”。
job_list = ["數(shù)據(jù)分析","數(shù)據(jù)統(tǒng)計","數(shù)據(jù)專員","數(shù)據(jù)挖掘","算法","大數(shù)據(jù)","開發(fā)工程師","運營", "軟件工程","前端開發(fā)","深度學(xué)習(xí)","ai","數(shù)據(jù)庫","倉庫管理","數(shù)據(jù)產(chǎn)品","客服", "java",".net","andrio","人工智能","c++","數(shù)據(jù)管理","測試","運維","數(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["崗位名稱"] = job_info["崗位名稱"].apply(Rename)job_info["崗位名稱"] = job_info["崗位名稱"].apply(lambda x:x.replace("數(shù)據(jù)專員","數(shù)據(jù)分析"))job_info["崗位名稱"] = job_info["崗位名稱"].apply(lambda x:x.replace("數(shù)據(jù)統(tǒng)計","數(shù)據(jù)分析"))
? ? ? ? 統(tǒng)一之后的“崗位名稱”如下圖所示:
?
? ? ? ? 對于“崗位薪資”字段的處理,重點在于對其單位格式轉(zhuǎn)換,在簡單觀察該字段后發(fā)現(xiàn),其存在“萬/年”、“萬/月”、“千/月”等不同單位,因此需要對其做一個統(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(["萬","千"])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:])def con_unit(x): if x["單位"] == "萬/月": z = x["平均薪資"]*10000 elif x["單位"] == "千/月": z = x["平均薪資"]*1000 elif x["單位"] == "萬/年": z = x["平均薪資"]/12*10000 return int(z)job_info["平均薪資"] = job_info.apply(con_unit,axis=1)job_info["單位"] = "元/月"
說明:首先我們對該字段進(jìn)行統(tǒng)計預(yù)覽,之后做一個數(shù)據(jù)篩選剔除異常單位與空值記錄,再計算出每個字段的平均工資,接著定義一個函數(shù),將格式換算為“元/月”,得到最終的“平均薪資”字段。
? ? ? ? 對于“公司規(guī)?!弊侄蔚奶幚磔^簡單,只需要定義一個if條件語句將其格式做一個轉(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)
job_info["職位信息"] = job_info["職位信息"].apply(lambda x:x.split("職能類別")[0])with open(r"E:/python爬蟲/數(shù)據(jù)處理/停用詞表.txt","r",encoding = "utf8") as f: stopword = f.read()stopword = stopword.split()#對“職業(yè)信息”字段進(jìn)行簡單處理,去除無意義的文字,構(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)行分類,求出每一個行業(yè)下各關(guān)鍵詞的詞頻統(tǒng)計,以便于后期做詞云圖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ù)存儲industry.to_excel(r"E:/python爬蟲/數(shù)據(jù)處理/詞云.xlsx")
#工作地點字段處理job_info["工作地點"] = job_info["工作地點"].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)驗與學(xué)歷要求字段處理job_info["工作經(jīng)驗"] = job_info["工作經(jīng)驗"].apply(lambda x:x.replace("無需","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())
? ? ? ? 我們針對清洗干凈后的數(shù)據(jù)另存為一個文檔,對源數(shù)據(jù)不做修改。
job_info.to_excel(r"E:/python爬蟲/前程無憂(已清洗).xlsx")
結(jié)論分析:從氣泡圖中可以看出,“數(shù)據(jù)”相關(guān)崗位數(shù)量較高的城市有:上海、深圳、廣州、北京、杭州、武漢等。
結(jié)論分析:通過條形圖可以看出,“數(shù)據(jù)”相關(guān)崗位用人需求達(dá)1000人以上的城市有15個,需求由高到低依次為:上海、深圳、廣州、北京、武漢、杭州、成都、南京、蘇州、無錫、西安、長沙、鄭州、重慶。其中上海用人需求高達(dá)10000人。
結(jié)論分析:從不同行業(yè)的用人需求與薪資對比可知,用人需求排名前4的行業(yè)分別:計算機(jī)軟件、互聯(lián)網(wǎng)、電子技術(shù)、計算機(jī)服務(wù);平均薪資排名前4的行業(yè)分別為:互聯(lián)網(wǎng)、計算機(jī)軟件、通信、專業(yè)服務(wù)。可以發(fā)現(xiàn),“數(shù)據(jù)”相關(guān)崗位在計算機(jī)領(lǐng)域需求大,薪資高,前景好。
結(jié)論分析:在發(fā)布的眾多崗位需求信息中,以民營公司為主,其崗位數(shù)量、用人需求極高,但薪資待遇一般,而上市公司的崗位數(shù)量一般,但薪資待遇好。
????????注:顏色深淺表示薪資高低,數(shù)字表示招聘人數(shù)
結(jié)論分析:根據(jù)突出顯示表可以發(fā)現(xiàn),在學(xué)歷要求方面,大專與本科生需求量較大;經(jīng)驗要求方面,3年以下相關(guān)經(jīng)驗的崗位占大多數(shù),而薪資方面,學(xué)歷越高,經(jīng)驗越豐富則薪資越高。因此可以判斷數(shù)據(jù)分析行業(yè)還是一個較新興的行業(yè),目前行業(yè)的基礎(chǔ)崗位較多,且具有豐富經(jīng)驗的專家較少。
?結(jié)論分析:上圖通過列舉了傳統(tǒng)制造業(yè)、計算機(jī)相關(guān)行業(yè)以及服務(wù)業(yè)三個行業(yè)進(jìn)行對比分析,三個行業(yè)對于“數(shù)據(jù)”相關(guān)崗位工作要求的共同點都是注重相關(guān)的行業(yè)經(jīng)驗及數(shù)據(jù)處理等能力,而計算機(jī)相關(guān)行業(yè)對于技術(shù)如開發(fā)、數(shù)據(jù)庫、系統(tǒng)維護(hù)等編程能力要求較高,傳統(tǒng)制造業(yè)和服務(wù)行業(yè)則更側(cè)重于業(yè)務(wù)分析、管理、團(tuán)隊合作綜合型能力等。
?
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) #頁面跳轉(zhuǎn) url_end = ".html?" url_all = url_pre + url_end url1.append(url_all)print("一級URL庫創(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)+"頁")print("成功提取"+str(len(url2))+"條二級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 崗位名稱 = 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 公司類型 = 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 公司名稱 = driver.find_element_by_xpath("http://div[@class = "com_msg"]/a/p").text 工作地點 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[0] 工作經(jīng)驗 = 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ā)布時間 = driver.find_elements_by_xpath("http://div[@class = "cn"]//p[@class = "msg ltype"]")[0].text.split("|")[4] except: 福利待遇 = "nan" 崗位名稱 = "nan" 薪資水平 = "nan" 職位信息 = "nan" 公司類型 = "nan" 公司規(guī)模 = "nan" 公司領(lǐng)域 = "nan" 公司名稱 = "nan" 工作地點 = "nan" 工作經(jīng)驗 = "nan" 學(xué)歷要求 = "nan" 招聘人數(shù) = "nan" 發(fā)布時間 = "nan" print("信息提取異常,棄用") finally: info = { "崗位名稱" : 崗位名稱, "公司名稱" : 公司名稱, "薪資水平" : 薪資水平, "工作經(jīng)驗" : 工作經(jīng)驗, "學(xué)歷要求" : 學(xué)歷要求, "工作地點" : 工作地點, "招聘人數(shù)" : 招聘人數(shù), "發(fā)布時間" : 發(fā)布時間, "公司類型" : 公司類型, "公司規(guī)模" : 公司規(guī)模, "公司領(lǐng)域" : 公司領(lǐng)域, "福利待遇" : 福利待遇, "職位信息" : 職位信息 } jobs_info.append(info)df = pd.DataFrame(jobs_info)df.to_excel(r"E:/python爬蟲/前程無憂招聘信息.xlsx")
import pandas as pdimport numpy as npimport jieba#數(shù)據(jù)讀取df = pd.read_excel(r"E:/python爬蟲/前程無憂招聘信息.xlsx",index_col=0)#數(shù)據(jù)去重與空值處理df.drop_duplicates(subset=["公司名稱","崗位名稱"],inplace=True)df[df["招聘人數(shù)"].isnull()]df.dropna(how="all",inplace=True)#崗位名稱字段處理df["崗位名稱"] = df["崗位名稱"].apply(lambda x:x.lower())counts = df["崗位名稱"].value_counts() target_job = ["算法","開發(fā)","分析","工程師","數(shù)據(jù)","運營","運維","it","倉庫","統(tǒng)計"]index = [df["崗位名稱"].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)計","數(shù)據(jù)專員","數(shù)據(jù)挖掘","算法","大數(shù)據(jù)","開發(fā)工程師", "運營","軟件工程","前端開發(fā)","深度學(xué)習(xí)","ai","數(shù)據(jù)庫","倉庫管理","數(shù)據(jù)產(chǎn)品", "客服","java",".net","andrio","人工智能","c++","數(shù)據(jù)管理","測試","運維","數(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["崗位名稱"] = job_info["崗位名稱"].apply(Rename)job_info["崗位名稱"] = job_info["崗位名稱"].apply(lambda x:x.replace("數(shù)據(jù)專員","數(shù)據(jù)分析"))job_info["崗位名稱"] = job_info["崗位名稱"].apply(lambda x:x.replace("數(shù)據(jù)統(tǒng)計","數(shù)據(jù)分析"))#崗位薪資字段處理index1 = job_info["崗位薪資"].str[-1].isin(["年","月"])index2 = job_info["崗位薪資"].str[-3].isin(["萬","千"])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["單位"] == "萬/月": z = x["平均薪資"]*10000 elif x["單位"] == "千/月": z = x["平均薪資"]*1000 elif x["單位"] == "萬/年": z = x["平均薪資"]/12*10000 return int(z)job_info["平均薪資"] = job_info.apply(con_unit,axis=1)job_info["單位"] = "元/月"#工作地點字段處理job_info["工作地點"] = job_info["工作地點"].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)驗與學(xué)歷要求字段處理job_info["工作經(jīng)驗"] = job_info["工作經(jīng)驗"].apply(lambda x:x.replace("無需","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("職能類別")[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ù)存儲industry.to_excel(r"E:/python爬蟲/數(shù)據(jù)預(yù)處理/詞云.xlsx") job_info.to_excel(r"E:/python爬蟲/數(shù)據(jù)預(yù)處理/前程無憂(已清洗).xlsx")
?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/121420.html
摘要:直接抄其中一份的結(jié)論吧各地區(qū)招聘公司數(shù)量和平均待遇??梢钥闯霾徽撌钦衅腹镜臄?shù)據(jù)還是平均待遇水平主要都是北上廣深杭州占優(yōu)勢。但事實證明,總是要有一些代價的。要學(xué)會看報錯信息。函數(shù)定義結(jié)束后需要按兩次回車重新回到提示符下。 又是寫在前面的亂七八糟 持續(xù)學(xué)習(xí)的第三天了,持續(xù)學(xué)習(xí)是一個不容易培養(yǎng)的好習(xí)慣,但是堅持就是勝利嘛~昨天因為一點點事情,所以沒能學(xué)習(xí)很長時間,今天要補(bǔ)回來。周末要搬家,...
摘要:成功爬取了拉鉤網(wǎng)上多個招聘崗位的具體信息后,數(shù)據(jù)可視化并得出分析結(jié)果如下從整體看,北上廣深杭這五個城市前端工程師招聘崗位,北京是遙遙領(lǐng)先,是深圳的兩倍,是廣州的三倍,其次到上海,深圳,杭州,廣州居末。 前前言 本文首發(fā)于 github blog 不想看爬蟲過程只想看職位錢途數(shù)據(jù)分析請看這里:前端招聘崗位分析C++招聘崗位分析JAVA招聘崗位分析PHP招聘崗位分析Python招聘崗位分析...
摘要:另外數(shù)學(xué)成為了一個關(guān)鍵詞,編程語言主要是等,運營也出現(xiàn)在詞云中說明數(shù)據(jù)分析師也需要有運營能力。 功能點 爬取數(shù)據(jù) 所有公司數(shù)據(jù),名稱簡寫,城市,行業(yè),職位數(shù)量,人數(shù)范圍,標(biāo)簽,介紹,融資階段,平均工資 github2016年度最受歡迎編程語言相應(yīng)年數(shù)薪水,城市,學(xué)歷要求,公司融資階段,公司行業(yè) 大數(shù)據(jù)行業(yè)五大崗位相應(yīng)年數(shù)薪水,城市,學(xué)歷要求,公司融資階段,公司行業(yè),崗位要求 編程語...
摘要:填寫自己對應(yīng)的網(wǎng)頁更改相應(yīng)數(shù)據(jù)的編碼格式遇到請求掛起當(dāng)前任務(wù),等操作完成執(zhí)行之后的代碼,當(dāng)協(xié)程掛起時,事件循環(huán)可以去執(zhí)行其他任務(wù)。 前言 2012,一個卡牌,一個雷...
摘要:編程基礎(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ù)...
閱讀 1330·2021-11-24 09:38
閱讀 3268·2021-11-22 12:03
閱讀 4202·2021-11-11 10:59
閱讀 2334·2021-09-28 09:36
閱讀 1042·2021-09-09 09:32
閱讀 3434·2021-08-05 10:00
閱讀 2541·2021-07-23 15:30
閱讀 2985·2019-08-30 13:12