摘要:因為本人在成都從事前端,所以這次爬取的關(guān)鍵詞既是成都,前端。僅僅有這個是不夠的,因為貌似拉勾網(wǎng)有反爬蟲,沒有好像得不到數(shù)據(jù)這個還待論證,至少我這邊是。
前言
今天是2018的第一天,首先祝各位小伙伴元旦快樂!
又到了新的一年,雖然離春節(jié)還有一段時間,但是程序狗打工不易啊,不關(guān)注薪資怎么行。今天要做的就是用圖表統(tǒng)計一下現(xiàn)在各公司的薪資狀況(雖然很多公司不能按照招聘上他們給的薪資來給)。
本次使用scrapy來做數(shù)據(jù)爬取,這是一個python的框架。因為本人在成都從事web前端,所以這次爬取的關(guān)鍵詞既是:成都,web前端。
scrapy startproject lagou
首先通過運行命令,得到一個爬蟲項目的基礎(chǔ)結(jié)構(gòu)。
接著按照scrapy的中文教程,通過在
start_urls = [ "https://www.lagou.com/jobs/list_web%E5%89%8D%E7%AB%AF?labelWords=sug&fromSearch=true&suginput=web" ]
spider中的start_urls配置好,應(yīng)該就能把拉勾網(wǎng)頁面拉取下來,然后再分析dom,提取字符串就可以了,無奈這種方法并不行。
起初也不知道,就用xpath一直找,后來發(fā)現(xiàn)找不到會報錯,這些各種錯誤對于我這個爬蟲萌新還是懵逼的。仔細(xì)查看他的network發(fā)現(xiàn),他的招聘信息都是在另外的ajax請求當(dāng)中,并且還是整理好的。
因為本人工作1年多,所以主要關(guān)注點是3年以下及3-5年,就提前選好了,城市和工作年限。該請求的傳參是formdata,其中first是首頁(其實寫代碼的時候并沒有注意這個參數(shù),所以一直傳的是true,貌似也沒什么影響),pn是當(dāng)前頁數(shù),kd是關(guān)鍵詞。
于是乎就去文檔查閱了一下,如何在scrapy中循環(huán)發(fā)送formdata請求。最終得到這樣一段可以執(zhí)行的代碼。
def start_requests(self): url = "https://www.lagou.com/jobs/positionAjax.json?gj=3%E5%B9%B4%E5%8F%8A%E4%BB%A5%E4%B8%8B%2C3-5%E5%B9%B4&xl=%E6%9C%AC%E7%A7%91&px=default&city=%E6%88%90%E9%83%BD&needAddtionalResult=false&isSchoolJob=0" for i in range(1, 14): formdata = {"first": "true", "pn": str(i), "kd": "web前端"} yield scrapy.FormRequest(str(url), callback=self.parseJson, formdata=formdata)
start_requests是發(fā)送post請求的方法,F(xiàn)ormRequest這個方法接收請求url,傳遞數(shù)據(jù)formdata,以及回調(diào)函數(shù)parseJson。parseJson在這里主要是接收獲取的數(shù)據(jù)。
僅僅有這個是不夠的,因為貌似拉勾網(wǎng)有反爬蟲,沒有header好像得不到數(shù)據(jù)(這個還待論證,至少我這邊是)。然后再settings.py文件中做了一些配置,配置主要有:
請求的header(主要是這幾項)
DEFAULT_REQUEST_HEADERS={ Accept:application/json, text/javascript, */*; q=0.01 Host:www.lagou.com Origin:https://www.lagou.com Referer:https://www.lagou.com/jobs/list_web%E5%89%8D%E7%AB%AF?px=default&gj=3%E5%B9%B4%E5%8F%8A%E4%BB%A5%E4%B8%8B,3-5%E5%B9%B4&city=%E6%88%90%E9%83%BD User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36 }
FEED_EXPORT_ENCODING(因為爬取到的中文是unicode字符)
FEED_EXPORT_ENCODING = "utf-8"
ROBOTSTXT_OBEY(這是一個爬蟲機器的協(xié)議,如果是true,表示遵守,有些網(wǎng)站禁止爬取的話,這個如果是true就爬不到了)
ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY(延時,這個也是去避免被反爬蟲,我這邊直接設(shè)置了比較長的時間,也沒有去測試多少合適,因為不設(shè)置也是會報錯的)
DOWNLOAD_DELAY = 10
基礎(chǔ)的配置項配置完畢之后,就是寫數(shù)據(jù)存儲的模型了,因為我只想去簡單統(tǒng)計一下,所以只存了薪資和工資這兩個字段,想要統(tǒng)計更多的信息,就直接繼續(xù)加就好了,這個比較簡單,在items.py中編寫
class LaGou(scrapy.Item): salary = scrapy.Field() company = scrapy.Field()
經(jīng)過這幾項配置,運行命令
scrapy crawl lagou -o a.json
就可以得到一份a.json,里面就是成都web前端相關(guān),工作年限為0-5年的數(shù)據(jù)信息了。有了這份數(shù)據(jù),接下來要做的就是數(shù)據(jù)處理了。
數(shù)據(jù)處理在之前的a.json當(dāng)中,大致可以得到一份之下的數(shù)據(jù),總計195條
[ {"salary": "8k-16k", "company": "xx有限公司"}, ...... ]
為了前端處理方便,直接改為js文件加一個變量引入html,即
var a = [ {"salary": "8k-16k", "company": "xx有限公司"}, ...... ]
這組數(shù)據(jù)的薪資是一個范圍,不方便我統(tǒng)計,于是為了便于操作數(shù)據(jù)把薪資取平均值,并統(tǒng)計提供相同的薪資的公司數(shù)目。
js代碼如下:
var arr = data.map(function (value) { return value.salary && value.salary.replace(/k|K/g, "").split("-").reduce(function (pV, nV) { return pV + nV / 2 }, 0) }).reduce(function (pV, nV) { nV in pV ? pV[nV]++ : (pV[nV] = 1); return pV; }, {}) //這里的data既是上邊的a變量
這段代碼主要作用是把薪資范圍計算成平均數(shù),然后再統(tǒng)計數(shù)組中相同的平均數(shù)的個數(shù)。代碼寫的隨意,可讀性較差,見諒。這段代碼處理過后,可得到類似如下數(shù)據(jù):
{"8":1,"8.5":3}
key是薪資均值,value是個數(shù)。
于是將key,value分別存入數(shù)組。這里遇到一個問題,就是開始我是這樣操作的
var xData=[...Object.keys(arr)] var yData=[...Object.values(arr)]
這么做有一個問題就是瀏覽器對于對象的遍歷規(guī)則,導(dǎo)致輸出的數(shù)組,小數(shù)都到了最外邊(比如這樣[1,2,1.5]),這樣在echarts下的圖表是亂序的。也沒有想到好的辦法去解決,就是對數(shù)組進(jìn)行一次排序,然后再根據(jù)排好的key生成相對應(yīng)的value數(shù)組,最終代碼:
var xData = [...Object.keys(arr).sort(function (a, b) { return a - b })] var yData = xData.map(function (v) { return arr[v] })
echarts比較簡單不贅述。將這兩組橫縱坐標(biāo)輸入echarts,得到最終效果:
本次做這個統(tǒng)計很多地方?jīng)]想清楚怎么更好的去表現(xiàn),所以做的很簡單,其實細(xì)致一點還可以去分類統(tǒng)計,按照公司融資情況,領(lǐng)域等等內(nèi)容,只要數(shù)據(jù)拿到都好說。另外很多地方可能寫的不夠好,主要我目前也不太會寫,比如之前反爬蟲那塊,貌似去做動態(tài)的用戶代理也能行,但我還是增加了延時,選擇了比較笨的方法。另外也不會python,但還好python比較好讀。因為這一塊才開始學(xué)習(xí),相信以后會越寫越好的,新的一年,加油!
update 2018/01/03昨天又把爬蟲優(yōu)化了一下,去掉了之前的延時,增加了動態(tài)用戶代理和動態(tài)IP代理,解決了之前爬蟲的效率問題,也擴大了數(shù)據(jù)量。
動態(tài)IP代理通過網(wǎng)上搜索免費的ip代理,獲取了如下一組ip:
PROXIES = [ {"ip_port": "106.39.179.244:80"}, {"ip_port": "65.52.223.99:80"}, {"ip_port": "1.52.248.207:3128"}, {"ip_port": "45.77.198.207:3128"}, {"ip_port": "177.125.119.16:8080"}, {"ip_port": "174.138.65.233:3128"}, ]
該IP過一段時間可能會失效,請自行搜索,如http://www.xicidaili.com/。
在middlewares.py中聲明該IP,之后聲明動態(tài)IP代理類
import random class ProxyMiddleware(object): def process_request(self, request, spider): proxy = random.choice(PROXIES) request.meta["proxy"] = "http://%s" % proxy["ip_port"] print("**************ProxyMiddleware no pass************" + proxy["ip_port"])
在settings.py文件中聲明該中間件
DOWNLOADER_MIDDLEWARES = { "scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware": 110, "tutorial.middlewares.ProxyMiddleware": 100, }動態(tài)用戶代理
在middlewares.py中聲明動態(tài)用戶代理類
class RandomUserAgent(object): """Randomly rotate user agents based on a list of predefined ones""" def __init__(self, agents): self.agents = agents @classmethod def from_crawler(cls, crawler): return cls(crawler.settings.getlist("USER_AGENTS")) def process_request(self, request, spider): # print "**************************" + random.choice(self.agents) request.headers.setdefault("User-Agent", random.choice(self.agents))
同樣在settings.py的中間件里聲明
DOWNLOADER_MIDDLEWARES = {
"tutorial.middlewares.RandomUserAgent": 1, "scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware": 110, "tutorial.middlewares.ProxyMiddleware": 100,
}
再次運行scrapy crawl lagou,即可得到新的數(shù)據(jù)。
在原有基礎(chǔ)上增加了對于工作年限和公司規(guī)模的篩選,并計算了平均值。
更新代碼如下:
// 指定圖表的配置項和數(shù)據(jù) initData(); function initData() { average = 0; arr = temData.map(function (value) { //之前正則篩選字符串有點問題,沒有考慮到有些公司格式為10k以上這種。 return value.salary && value.salary.replace(/[k|Ku4e00-u9fa5]/g, "").split("-").reduce(function (pV, nV, i, array) { if (array.length > 1) { average = Number(average) + pV + nV / 2 return pV + nV / 2 } else { average = +average + Number(nV) return nV } // return array.length > 1 ? pV + nV / 2 : nV }, 0) }).reduce(function (pV, nV) { nV in pV ? pV[nV]++ : (pV[nV] = 1); return pV; }, {}) average = (average / temData.length).toFixed(2) }
暫時這樣,通過之后的學(xué)習(xí),還會不斷的優(yōu)化。
展示效果:
源碼地址:https://github.com/jiwenjiang...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/41165.html
摘要:因為本人在成都從事前端,所以這次爬取的關(guān)鍵詞既是成都,前端。僅僅有這個是不夠的,因為貌似拉勾網(wǎng)有反爬蟲,沒有好像得不到數(shù)據(jù)這個還待論證,至少我這邊是。 前言 showImg(https://segmentfault.com/img/bV1g4S?w=700&h=490); 今天是2018的第一天,首先祝各位小伙伴元旦快樂!又到了新的一年,雖然離春節(jié)還有一段時間,但是程序狗打工不易啊,不...
摘要:然后準(zhǔn)備再去抓下拉勾網(wǎng)的招聘數(shù)據(jù),這也是個相對優(yōu)秀的專業(yè)招聘網(wǎng)站了,數(shù)據(jù)也相當(dāng)多,想當(dāng)初找實習(xí)找正式工作,都是在這兩個上找的,其他的網(wǎng)站幾乎都沒看。 原文地址:http://www.jtahstu.com/blog/s... Pyhton爬蟲實戰(zhàn) - 抓取BOSS直聘職位描述 和 數(shù)據(jù)清洗 零、致謝 感謝BOSS直聘相對權(quán)威的招聘信息,使本人有了這次比較有意思的研究之旅。 由于爬蟲持續(xù)...
摘要:然后準(zhǔn)備再去抓下拉勾網(wǎng)的招聘數(shù)據(jù),這也是個相對優(yōu)秀的專業(yè)招聘網(wǎng)站了,數(shù)據(jù)也相當(dāng)多,想當(dāng)初找實習(xí)找正式工作,都是在這兩個上找的,其他的網(wǎng)站幾乎都沒看。 原文地址:http://www.jtahstu.com/blog/s... Pyhton爬蟲實戰(zhàn) - 抓取BOSS直聘職位描述 和 數(shù)據(jù)清洗 零、致謝 感謝BOSS直聘相對權(quán)威的招聘信息,使本人有了這次比較有意思的研究之旅。 由于爬蟲持續(xù)...
摘要:愛寫作者愛寫前言看了很多網(wǎng)站,只發(fā)現(xiàn)獲取拉勾網(wǎng)招聘信息是只用方式就可以得到,應(yīng)當(dāng)是非常簡單了。在環(huán)境下運行通過數(shù)據(jù)爬取篇偽造瀏覽器訪問拉勾網(wǎng)打開瀏覽器,進(jìn)入拉勾網(wǎng)官網(wǎng),右鍵檢查,調(diào)出開發(fā)者模式。 [TOC] 愛寫bug(ID:icodebugs)作者:愛寫bug 前言: ? 看了很多網(wǎng)站,只發(fā)現(xiàn)獲取拉勾網(wǎng)招聘信息是只用post方式就可以得到,應(yīng)當(dāng)是非常簡單了。推薦剛接觸數(shù)據(jù)分析...
摘要:拉勾網(wǎng)的爬蟲還是有一定的難度的所以我們今天就爬取試一下其實并沒有太大的難度只要我們用好分析一下請求就會其實沒有什么難度上代碼親測可用拉鉤代碼 拉勾網(wǎng)的爬蟲還是有一定的難度的 所以我們今天就爬取試一下 其實并沒有太大的難度 只要我們用好network 分析一下請求 就會其實沒有什么難度 上代碼 2019-05-22 親測可用 拉鉤代碼
閱讀 2959·2021-11-25 09:43
閱讀 3336·2021-11-24 09:39
閱讀 2844·2021-09-22 15:59
閱讀 2215·2021-09-13 10:24
閱讀 520·2019-08-29 17:02
閱讀 2111·2019-08-29 13:23
閱讀 3071·2019-08-29 13:06
閱讀 3550·2019-08-29 13:04