本來今天打算把以前的爬蟲記錄復制粘貼過來的,后來想想有點沒意思,就想再寫一次爬蟲,順便加上之前學的可視化數據分析。
有點糊塗,不知道該從哪里說起,也不知道該怎么講。所以還是按照我自己的爬蟲步驟講吧
這里建議用jupyter notebook編輯,方便數據的展示
總的步驟就是:①導入模塊 ②配置繪圖風格 ③反爬 ④開始寫爬蟲代碼 ⑤整合 ⑥繪圖
大概就是以上這些步驟。
①導入包。今天想通過爬取數據繪制的圖像有:條形圖、餅圖、地理熱力圖
#導入要用到的模塊 import requests #網絡請求 import re import pandas as pd #數據框操作 import numpy as np import matplotlib.pyplot as plt #繪圖 import matplotlib as mpl #配置字體 from pyecharts import Geo #地理圖 import time #增加延時 import random
這里可能會出現的問題:這些模塊都要自己下載的哦,具體方法可以自己去網上找,其實挺簡單。大部分都是pip install就就解決的事情。
還有一些可能要自己到文件下載網站下載,還會讓你選相應的匹配文件,這里的匹配是python版本匹配、位數匹配,如果不知道的話就打開CMD命令窗口進入python,輸入以下:
import pip print(pip.pep425tags.get_supported())
我的話就出現了:

所以我選的應該是箭頭所指的格式的文件。
②設置繪圖格式和繪圖風格
mpl.rcParams['font.sans-serif'] = ['SimHei'] #這個是繪圖格式,不寫這個的話橫坐標無法變成我們要的內容 #配置繪圖風格
plt.rcParams['axes.labelsize'] = 8. plt.rcParams['xtick.labelsize'] = 12. plt.rcParams['ytick.labelsize'] = 12. plt.rcParams['legend.fontsize'] =10. plt.rcParams['figure.figsize'] = [8.,8.]
上面的意思通過英文很容易理解,
③反爬蟲
反爬措施可以通過firefox里的請求頭里的信息實現,直接把請求頭里的信息復制過來就好,用其他瀏覽器的也行,把cookies注釋掉,因為不要登錄信息。
我用的是火狐。首先按F12,在網絡里找到列表里的postion開頭的內容,然后找到請求頭(其他瀏覽器可能是Rrequest什么的)

將請求頭里的內容全部復制下來,需要注意的是,通過火狐瀏覽器復制的請求頭會出現”...“,當我們復制過來發現有省略號時,把那個有省略號的地方打全。只需雙擊目標內容,請求頭那里就會出現完整的句子,我把cookie注釋掉了,因為不需要。代碼如下
header = {'Accept':'application/json, text/javascript, */*; q=0.01', 'Accept-Encoding':'gzip, deflate, br', 'Accept-Language':'zh-CN,zh;q=0.8', 'Connection':'keep-alive', 'Content-Length':'56', 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8', #Cookie:LGUID=20161214153335-9f0eacc2-c1cf-11e6-bd6c-5254005c3644; user_trace_token=20180122030442-efefe00e-fedd-11e7-b2cb-525400f775ce; LG_LOGIN_USER_ID=e619b07cb5d026e017473de3d4ef1bb5a3da9a0ddd6ea0a5; gray=resume; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%227288096%22%2C%22%24device_id%22%3A%221626117eb3016-0703ff024b7ae5-71292b6e-1049088-1626117eb3569%22%2C%22first_id%22%3A%221626117eb3016-0703ff024b7ae5-71292b6e-1049088-1626117eb3569%22%7D; WEBTJ-ID=20180403125347-16289da9860300-0dcabf1bb6b166-71292b6e-1049088-16289da98619b; login=true; unick=%E6%8B%89%E5%8B%BE%E7%94%A8%E6%88%B73739; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=0; gate_login_token=63a7401b950e42d41a03d8ce1db134ac22aeefc46c120c43; index_location_city=%E6%B7%B1%E5%9C%B3; JSESSIONID=ABAAABAAADEAAFIDFE252684FD90098F44851E32F917A9F; TG-TRACK-CODE=search_code; SEARCH_ID=e267bafce9b0431d8f8a867e48f2a7bf; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1522167431,1522215930,1522219100,1522731245; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1522741185; _gat=1; _ga=GA1.2.983742987.1481700649; _gid=GA1.2.1178844706.1522731227; LGSID=20180403154252-9d580c63-3712-11e8-b228-525400f775ce; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Fjobs%2Flist_%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%3Fcity%3D%25E6%25B7%25B1%25E5%259C%25B3%26cl%3Dfalse%26fromSearch%3Dtrue%26labelWords%3D%26suginput%3D; LGRID=20180403154252-9d580e4e-3712-11e8-b228-525400f775ce; _putrc=2C1A435C1A81EDB8
'Host':'www.lagou.com', 'Origin':'https://www.lagou.com', 'Referer':'https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?city=%E6%B7%B1%E5%9C%B3&cl=false&fromSearch=true&labelWords=&suginput=', 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.3964.2 Safari/537.36', 'X-Anit-Forge-Code':'0', 'X-Anit-Forge-Token':'None', 'X-Requested-With':'XMLHttpRequest'}
④開始寫爬蟲代碼
首先,還是得先分析下網頁信息
我們翻到第一頁,其網頁代碼是:https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=&fromSearch=true&suginput=
第二頁,其網頁代碼是: https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=&fromSearch=true&suginput=
可以發現,不同頁數的網址並沒有區別,所以可以判斷這是一個動態網頁,真正的網址其實在消息頭(Headers)。用F12打開Network一欄

然后隨便點開一頁,比如說第四頁,可以看到內容欄的第一個以position開頭的東西,自己點擊查看下,之后再一層一層打開,在result下面有很多我們想要的信息。

然后可以點開到參數那里,最后一欄有“表單數據”,kd是我們搜索的關鍵詞,pn是頁數。first那里我也不知道是什么,不用管它。

把這個復制下到txt里,因為等等我們還有一些東西需要復制。
但我們現在可以開始寫一些代碼來測試下了。
dat = {'first':'false', 'kd':'數據分析', 'pn':'3'} #這是我們剛剛復制的內容
url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false' #真實網址
html = requests.request('POST',url,data=dat,headers=header) #進行請求
接着來測試下我們有沒有翻車!
html.status_code #返回200說明沒翻車,對比404,返回的是404代表翻車了,200是服務器返回的正常消息
我的結果截圖是:說明沒問題,但不一定出現200就一定沒問題。

再測試我們爬的內容↓
html.text #如果出現”操作頻繁“就是是被反爬了,所以一定要實施反爬措施,其實反爬措施有好幾種,瀏覽器代理、IP地址代理都可以
我出現的結果:說明爬取成功

接着,要思考下,我們需要爬什么內容,我想爬工作經驗、地區、福利、待遇、企業名稱等內容
在jupyter notebook里,Ctrl+F,輸入companyid,然后選取你可能需要的字段

復制以后,粘貼到文本上,然后對自己需要的內容進行模糊匹配,就是把其變成(.*?),不需要的內容直接寫成.*?,就是不用加括號。對這方面不熟的話,就去看看正則表達式
我是這么寫的:

然后寫代碼進行正則提取:
#用正則表達式來提取數據 #在jupyterF5找出你想要的信息,然后復制你想要的信息,像我的話直接復制到薪水就可以了
data = re.findall('"companyId":.*?,"workYear":"(.*?)","education":"(.*?)","city":"(.*?)","positionName":"(.*?)","companyLogo":".*?","companyShortName":"(.*?)","positionLables":.*?,"industryLables":.*?,"businessZones":.*?,"score":.*?,"approve":.*?,"jobNature":".*?","companyLabelList":(.*?),"publisherId":.*?,"district":"(.*?)","companySize":".*?","createTime":".*?","positionAdvantage":".*?","salary":"(.*?)"',html.text)
⑤整合
到了這里我們可以把我們寫的、測試的東西整合到一起了,
我們爬取的內容一共有30頁,翻頁用for循環來實現。for i in range的時候要慢慢爬,不能一下子就爬到很后面,這樣也會被發現的。 可以這樣理解:你翻頁翻太快很明顯就不是人為的,所以很容易被反爬。所以這時候我們要import time,就是增加延時。time.sleep(2),停兩秒在翻頁。
但是每次都是停兩秒才翻頁的話,就太准確啦,也容易被反爬。所以再加載一個隨機模塊,來隨機選取秒數,我將秒數設置為2到10秒。最后整合如下:
#數據分析崗位有30頁,用for循環實現翻頁
for i in range(1,31): #寫入真實網址,不是網頁上的網址,是在消息頭那,別的瀏覽器是Headers
url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
#提交數據,在參數那一欄,把這個復制過來,然后加上引號和逗號
dat = {'first':'false', 'kd':'數據分析', 'pn':'3',} time.sleep(random.randint(2,10)) html = requests.request('POST',url,data=dat,headers=header) #用正則表達式來提取數據
#在jupyterF5找出你想要的信息,然后復制你想要的信息,像我的話直接復制到薪水就可以了
data = re.findall('"companyId":.*?,"workYear":"(.*?)","education":"(.*?)","city":"(.*?)","positionName":"(.*?)","companyLogo":".*?","companyShortName":"(.*?)","positionLables":.*?,"industryLables":.*?,"businessZones":.*?,"score":.*?,"approve":.*?,"jobNature":".*?","companyLabelList":(.*?),"publisherId":.*?,"district":"(.*?)","companySize":".*?","createTime":".*?","positionAdvantage":".*?","salary":"(.*?)"',html.text) #轉成數據框
data2 = pd.DataFrame(data) #寫入本地
#header、index是行名、列名的意思,讓他們等於False的意思是,原來的行名和列名我們都不要,mode=a+就是要追加信息,
#就是你要繼續加信息的時候,他會往下寫。而不是把你之前的信息覆蓋掉
#執行完畢后,可在剛剛的文件夾里發現csv文件
data2.to_csv('C:\\Users\\Administrator\\Desktop\\456\\lagoujob.csv',header=False,index=False,mode='a+')
執行以上代碼后可在文件夾里找到一個csv文件,要等一會的,不是馬上就能爬好的。↓


工作經驗學歷什么的是我在這個文件里自己加上去的,你也可以自己在代碼里寫
現在來讀取下這個csv文件↓
data3 = pd.read_csv(r'C:\\Users\\Administrator\\Desktop\\456\\lagoujob.csv',encoding='gbk') #出現錯誤的話試試utf8,路徑不能出現中文,會出現錯誤
讀取前面的內容



⑥繪圖
查看學下歷分類的狀況以及計數

根據學歷狀況繪制柱形圖↓
data3['學歷'].value_counts().plot(kind='bar') #繪制條形圖
plt.show #顯示圖片

根據學歷狀況繪制條形圖↓
data3['學歷'].value_counts().plot(kind='barh') #繪制倒置的條形圖
plt.show #顯示圖片

根據”工作經驗“繪制條形圖↓
data3['工作經驗'].value_counts().plot(kind='barh') #繪制條形圖
plt.show #顯示圖片

根據地區繪制餅圖↓
#繪制餅圖
data3['地區'].value_counts().plot(kind='pie',autopct='%1.2f%%') plt.show #顯示圖片

看到網上有的人可以把餅圖化成這樣:

不知道怎么搞的,不知道怎么設置參數才能畫成這樣,知道的大哥麻煩告訴下~~~~
-----------------------------------
最后繪制熱力圖,繪制熱力圖的時候出現了好多問題啊,搞了特別久。。我其實已經安裝了pyecharts了,但怎么搞都顯示不出地圖。查了很多資料才發現:“
pyecharts v0.3.2以后,pyecharts 將不再自帶地圖 js 文件。如用戶需要用到地圖圖表,可自行安裝對應的地圖文件包。
下面介紹如何安裝。
地圖文件被分成了三個 Python 包,分別為:
全球國家地圖: echarts-countries-pypkg (1.9MB)
中國省級地圖: echarts-china-provinces-pypkg (730KB)
中國市級地圖: echarts-china-cities-pypkg (3.8MB)
直接使用python的pip安裝:
”
代碼如下,在CMD命令窗口輸入
pip install echarts-countries-pypkg pip install echarts-china-provinces-pypkg pip install echarts-china-cities-pypkg
安裝完地圖包以后一定要重啟jupyter notebook,不然是無法顯示地圖的。
我在后面重新跑了一次爬蟲的代碼,發現我上面的爬蟲其實沒爬到30頁,原因可能是我在它沒爬完就直接打開那個CSV文件進行編輯了。第二次跑的時候去洗了個澡,發現洗完新CSV文件里的東西比第一次跑多得多,所以還是要有耐心呀!然后制作熱力圖就用第二次跑的來做。
首先,我們要先讀取那個新的CSV文件↓
data3 = pd.read_csv(r'C:\\Users\\Administrator\\Desktop\\456\\lagoujob1.csv',encoding='gbk') #出現錯誤的話試試utf8,路徑不能出現中文,會出現錯誤
#從lambda一直到*1000,是一個匿名函數,*1000的原因是這里顯示的是幾K幾K的,我們把K切割掉,只要數字,就*1000了
data4 = list(map(lambda x:(data3['工作地區'][x],eval(re.split('k|K',data3['工資待遇'][x])[0])*1000),range(len(data3))))
#再把data4框架起來
data5 = pd.DataFrame(data4) data5
#轉化成geo所需要的故事,也是用匿名函數,在data5中,按照地區分組,然后根據地區來計算工資的平均值,將其變成序列后再分組
data6 = list(map(lambda x:(data5.groupby(0).mean()[1].index[x],data5.groupby(0).mean()[1].values[x]),range(len(data5.groupby(0)))))
#geo = Geo('主標題','副標題',字體顏色='白色',字體位置='中間',寬度=1200,高度=600,背景顏色=‘#404a59')
geo = Geo("全國數據分析工資分布", "制作:風吹白楊的安妮", title_color="#fff", title_pos="center",width=1200, height=600, background_color='#404a59') #屬性、數值對應的映射關系,attr是屬性,value是該屬性對應的數值,比如說北京對應15000,杭州對應10000
attr, value =geo.cast(data6) #這個是對地圖進行設置,第一個參數設置為空值,我看別人這么設置我也這么設置了,下次查查為什么,第二個參數是屬性,第三個為對應數值, #第四個參數是可視范圍,把工資區間換算成了0到300. 第五個很容易出錯,我之前安裝完地圖還是出錯的原因就是沒加上maptype=''china',一定要加上,第六個圖例類型寫上熱力圖, #第七個參數是地圖文本字體顏色為白色,第八個是標識大小,第九個是否進行可視化=True.
geo.add("", attr, value, visual_range=[0, 300],maptype='china',type='heatmap' ,visual_text_color="#fff", symbol_size=15, is_visualmap=True) geo.show_confi geo.render('我的圖片.html')
我自己直接輸入geo想來看看圖片的時候,顯示的是空白,我也不知道是怎么回事,但返回目錄可看到html里面可以顯示圖片↓

打開后:

數據分析崗位的學歷要求如下:

工資概況:

工作經驗要求:

招聘地區:

看看用后來爬的數據。可以發現數據分析崗位中,本科學歷是最基本的,可能是本科生的統計學、高等數學、線性代數的基礎較好,有良好的算法和數據分析思維,然后至於碩士的話,我認為可能是碩士深造的比較多,數據分析可能滿足不了他們的職位需求,大部分都可能去做大數據開發或者數據挖掘、機器學習去了。工資的話,10k-20k是最多的,看了下“滲透工程師”的工資,最多的是5k-10k的,並且滲透工程師貌似對學歷的要求也不高?這可能就是門檻的問題了,不過我認為只要一個人將自己的工作做到了極致,管他毛門檻毛學歷。招聘地區也是北上廣最多,至於深圳。。。我檢查過了,是我依然沒爬完全!!麻蛋,估計還是被反爬了,查了下知乎,有如下措施:

下次再爬就試試好了,再見。
參考文章:
《利用pyecharts實現地圖可視化》
https://blog.csdn.net/xxzj_zz2017/article/details/79601135
另一篇
https://blog.csdn.net/TheLittlePython/article/details/79605694
