Python爬取前程無憂職位資訊
阿新 • • 發佈:2021-06-20
一、選題背景
剛畢業往往會為自己不知道每個職位之間各種待遇的差異而迷茫,所以為了瞭解畢業後職位的待遇等方面做多種參考,貨比三家。
1.資料來源
前程無憂(https://www.51job.com/)
2.爬取內容
爬取內容包括職位名稱,公司名稱,地點,薪資,學歷要求,以及釋出日期等。
二、實現爬取的步驟
1.程式碼所需包
1 import urllib.request 2 import xlwt 3 import re 4 import urllib.parse 5 import time
2.進入前程無憂官網,搜尋職位資訊
3.開啟開發者模式
4.模擬瀏覽器
1 header={2 'Host':'search.51job.com', 3 'Upgrade-Insecure-Requests':'1', 4 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36' 5 }
5.為了實現爬取,我寫了一個能夠實現輸入想了解的職位就能爬取相關內容的函式
1 #page是頁數,item是輸入的字串,見後文 2 def getfront(page,item):3 #先把字串轉成十六進位制編碼 4 result = urllib.parse.quote(item) 5 ur1 = result+',2,'+ str(page)+'.html' 6 ur2 = 'https://search.51job.com/list/000000,000000,0000,00,9,99,' 7 res = ur2+ur1 #拼接網址 8 a = urllib.request.urlopen(res)9 # 讀取原始碼並轉為unicode 10 html = a.read().decode('gbk') 11 return html
1 def getInformation(html): 2 #匹配換行符 3 reg = re.compile(r'class="t1 ">.*? <a target="_blank" title="(.*?)" href="(.*?)".*? <span class="t2"><a target="_blank" title="(.*?)" href="(.*?)".*?<span class="t3">(.*?)</span>.*?<span class="t4">(.*?)</span>.*?<span class="t5">(.*?)</span>.*?',re.S) 4 items=re.findall(reg,html) 5 return items
除了爬取基本資訊外,還把職位超連結後的網址,以及公司超連結的網址爬取下來了。
6.把爬取的資訊以Excel檔案形式儲存起來,比較清晰直觀。
1 #新建表格空間 2 excel1 = xlwt.Workbook() 3 # 設定單元格格式 4 sheet1 = excel1.add_sheet('Job', cell_overwrite_ok=True) 5 6 sheet1.write(0, 0, '序號') 7 8 sheet1.write(0, 1, '職位') 9 10 sheet1.write(0, 2, '公司名稱') 11 12 sheet1.write(0, 3, '公司地點') 13 14 sheet1.write(0, 4, '公司性質') 15 16 sheet1.write(0, 5, '薪資') 17 18 sheet1.write(0, 6, '學歷要求') 19 20 sheet1.write(0, 7, '工作經驗') 21 22 sheet1.write(0, 8, '公司規模') 23 24 sheet1.write(0, 9, '公司型別') 25 26 sheet1.write(0, 10,'公司福利') 27 28 sheet1.write(0, 11,'釋出時間')
爬取程式碼如下
1 number = 1 2 item = input() 3 4 for j in range(1,1000): 5 try: 6 print("正在爬取第"+str(j)+"頁資料...") 7 #呼叫獲取網頁原碼 8 html = getfront(j,item) 9 10 for i in getInformation(html): 11 try: 12 #職位網址 13 url1 = i[1] 14 res1 = urllib.request.urlopen(url1).read().decode('gbk') 15 company = re.findall(re.compile(r'<div class="com_tag">.*?<p class="at" title="(.*?)"><span class="i_flag">.*?<p class="at" title="(.*?)">.*?<p class="at" title="(.*?)">.*?',re.S),res1) 16 17 job_need = re.findall(re.compile(r'<p class="msg ltype".*?>.*? <span>|</span> (.*?) <span>|</span> (.*?) <span>|</span> .*?</p>',re.S),res1) 18 19 welfare = re.findall(re.compile(r'<span class="sp4">(.*?)</span>',re.S),res1) 20 print(i[0],i[2],i[4],i[5],company[0][0],job_need[2] 21 [0],job_need[1][0],company[0][1],company[0][2],welfare,i[6]) 22 sheet1.write(number,0,number) 23 24 sheet1.write(number,1,i[0]) 25 26 sheet1.write(number,2,i[2]) 27 28 sheet1.write(number,3,i[4]) 29 30 sheet1.write(number,4,company[0][0]) 31 32 sheet1.write(number,5,i[5]) 33 34 sheet1.write(number,6,job_need[1][0]) 35 36 sheet1.write(number,7,job_need[2][0]) 37 38 sheet1.write(number,8,company[0][1]) 39 40 sheet1.write(number,9,company[0][2]) 41 42 sheet1.write(number,10,(" ".join(str(i) for i in welfare))) 43 44 sheet1.write(number,11,i[6]) 45 46 number+=1 47 excel1.save("51job.xls") 48 #休息間隔,避免爬取海量資料時被誤判為攻擊,IP遭到封禁 49 time.sleep(0.3) 50 except: 51 pass 52 except: 53 pass
結果如下:
三、資料清洗與處理
1.先開啟檔案
1 #coding:utf-8 2 import pandas as pd 3 import re 4 5 #除此之外還要安裝xlrd包 6 7 data = pd.read_excel(r'51job.xls',sheet_name='Job') 8 result = pd.DataFrame(data)
清洗思路:
1、出現有空值的資訊,直接刪除整行
1 a = result.dropna(axis=0,how='any') 2 #輸出全部行,不省略 3 pd.set_option('display.max_rows',None)
2.職位出錯(爬取職位與預想職位無關)
1 1 b = u'資料' 2 2 number = 1 3 3 li = a['職位'] 4 4 for i in range(0,len(li)): 5 5 try: 6 6 if b in li[i]: 7 7 #print(number,li[i]) 8 8 number+=1 9 9 else: 10 10 a = a.drop(i,axis=0) 11 11 except: 12 12 pass
3.其他地方出現的資訊錯位,比如在學歷裡出現 ‘招多少人’
1 b2= u'人' 2 li2 = a['學歷要求'] 3 for i in range(0,len(li2)): 4 try: 5 if b2 in li2[i]: 6 #print(number,li2[i]) 7 number+=1 8 a = a.drop(i,axis=0) 9 except: 10 pass
4.轉換薪資單位不一致
1 b3 =u'萬/年' 2 b4 =u'千/月' 3 li3 = a['薪資'] 4 5 #註釋部分的print都是為了除錯用的 6 7 for i in range(0,len(li3)): 8 try: 9 if b3 in li3[i]: 10 x = re.findall(r'\d*\.?\d+',li3[i]) 11 #print(x) 12 13 #轉換成浮點型並保留兩位小數 14 min_ = format(float(x[0])/12,'.2f') 15 max_ = format(float(x[1])/12,'.2f') 16 li3[i][1] = min_+'-'+max_+u'萬/月' 17 if b4 in li3[i]: 18 x = re.findall(r'\d*\.?\d+',li3[i]) 19 #print(x) 20 21 #input() 22 min_ = format(float(x[0])/10,'.2f') 23 max_ = format(float(x[1])/10,'.2f') 24 li3[i][1] = str(min_+'-'+max_+'萬/月') 25 print(i,li3[i]) 26 27 except: 28 pass
清洗完成後儲存到新的Excel檔案裡。
1 a.to_excel('51job2.xlsx', sheet_name='Job', index=False)
四、資料視覺化
經過視覺化處理能使資料更加直觀,更有利於分析 甚至可以說視覺化是資料探勘最重要的內容。
1.檢視需要的包
1 # -*- coding: utf-8 -*- 2 import pandas as pd 3 import re 4 from pyecharts import Funnel,Pie,Geo 5 import matplotlib.pyplot as plt
2.開啟檔案
1 file = pd.read_excel(r'51job2.xls',sheet_name='Job') 2 f = pd.DataFrame(file) 3 pd.set_option('display.max_rows',None)
3.建立多個列表來單獨存放薪資,工作經驗,學歷要求,公司地點等資訊
1 add = f['公司地點'] 2 sly = f['薪資'] 3 edu = f['學歷要求'] 4 exp = f['工作經驗'] 5 address =[] 6 salary = [] 7 education = [] 8 experience = [] 9 for i in range(0,len(f)): 10 try: 11 a = add[i].split('-') 12 address.append(a[0]) 13 #print(address[i]) 14 s = re.findall(r'\d*\.?\d+',sly[i]) 15 s1= float(s[0]) 16 s2 =float(s[1]) 17 salary.append([s1,s2]) 18 #print(salary[i]) 19 education.append(edu[i]) 20 #print(education[i]) 21 experience.append(exp[i]) 22 #print(experience[i]) 23 except: 24 pass
4.工作經驗—薪資圖 與 學歷—薪資圖
1 #定義存放最低薪資的列表 2 min_s=[] 3 #定義存放最高薪資的列表 4 max_s=[] 5 for i in range(0,len(experience)): 6 min_s.append(salary[i][0]) 7 max_s.append(salary[i][0]) 8 9 my_df = pd.DataFrame({'experience':experience, 'min_salay' : min_s, 10 #關聯工作經驗與薪資 11 'max_salay' : max_s}) 12 data1 = my_df.groupby('experience').mean()['min_salay'].plot(kind='line') 13 plt.show() 14 15 my_df2 = pd.DataFrame({'education':education, 'min_salay' : min_s, 16 #關聯學歷與薪資 17 'max_salay' : max_s}) 18 data2 = my_df2.groupby('education').mean()['min_salay'].plot(kind='line') 19 plt.show()
5.學歷要求圓環圖
1 def get_edu(list): 2 education2 = {} 3 for i in set(list): 4 education2[i] = list.count(i) 5 return education2 6 dir1 = get_edu(education) 7 8 # print(dir1) 9 10 attr= dir1.keys() 11 value = dir1.values() 12 pie = Pie("學歷要求") 13 pie.add("", attr, value, center=[50, 50], is_random=False, radius=[30, 75], rosetype='radius', 14 is_legend_show=False, is_label_show=True,legend_orient='vertical') 15 pie.render('學歷要求玫瑰圖.html')
6.大資料城市需求地理位置分佈圖
1 def get_address(list): 2 address2 = {} 3 for i in set(list): 4 address2[i] = list.count(i) 5 6 address2.pop('異地招聘') 7 8 #address2.pop('山東') 9 #address2.pop('怒江') 10 #address2.pop('池州') 11 12 return address2 13 14 dir2 = get_address(address) 15 16 #print(dir2) 17 18 geo = Geo("大資料人才需求分佈圖", title_color="#2E2E2E", 19 title_text_size=24,title_top=20,title_pos="center", width=1300,height=600) 20 21 attr2 = dir2.keys() 22 value2 = dir2.values() 23 24 geo.add("",attr2, value2, type="effectScatter", is_random=True, visual_range=[0, 1000], maptype='china',symbol_size=8, effect_scale=5, is_visualmap=True) 25 26 geo.render('大資料城市需求分佈圖.html')
7.工作經驗要求漏斗圖
1 def get_experience(list): 2 experience2 = {} 3 for i in set(list): 4 5 experience2[i] = list.count(i) 6 7 return experience2 8 9 dir3 = get_experience(experience) 10 11 #print(dir3) 12 13 attr3= dir3.keys() 14 value3 = dir3.values() 15 funnel = Funnel("工作經驗漏斗圖",title_pos='center') 16 17 funnel.add("", attr3, value3,is_label_show=True,label_pos="inside", label_text_color="#fff",legend_orient='vertical',legend_pos='left') 18 19 funnel.render('工作經驗要求漏斗圖.html')
五、總結
本次主題的爬蟲因基礎薄弱進行的時間較久,但結果還是好的。通過Execll檔案和視覺化分析可以清晰直觀的瞭解到應聘職位的各種要求,
基本達到了想要的結果。但是pyecharts裡面的圖還有很多種,還是要繼續慢慢發掘,加強自己的專業知識。