最近有很多程序員又開始找工做了,爲了瞭解目前技術類各職位的數量、薪資、招聘公司、崗位職責及要求,我爬取了拉勾網北上廣深4個城市的招聘數據,共3w條。職位包括:人工智能(AI)、大數據、數據分析、後端(Java、C|C++、PHP、Python)、前端、Android、iOS、嵌入式和測試。下面我將分兩部分進行介紹,第一部分是數據抓取;第二部分是數據分析。如需源代碼在公衆號(見文末)回覆關鍵字 職位 便可。前端
這裏我並非經過傳統的抓網頁,解析HTML代碼的方式爬取數據,而是用 Charles 軟件抓取拉鉤APP請求數據的接口實現。python
大概的流程是啓動Charles -> 手機鏈接Charles代理(兩者需處於同一個局域網)-> 打開APP請求數據->觀察Charles截的包,從中找到咱們想要的接口git
首先,找到搜索職位的接口程序員
/v1/entry/positionsearch/searchPosition複製代碼
這是一個 POST 請求,咱們還要找到請求的 header 和 body,最關鍵的 header 和 body 以下json
header:後端
'X-L-REQ-HEADER': '{"deviceType":150,"userType":0,"lgId":"11835BCC-8815-456A-A094-64FB2B9323EF_1585362240","reqVersion":73600,"appVersion":"7.36.0","userToken":"xxx"}'
'content-type': "application/json"複製代碼
其中,userToken字段每一個不同,須要本身抓包肯定緩存
bodybash
{"tagType": "", "isAd": "1", "showId": "", "district": "", "keywordSource": 0, "keyword": "數據開發", "salaryUpper": 0, "hiTag": "", "longitudeAndLatitude": "-1.000000,-1.000000", "pageNo": 1, "sort": 0, "pageSize": 15, "refreshHiTagList": True, "lastShowCompanyId": 0, "nearByKilometers": "", "city": "北京", "businessZone": "", "shieldDeliveyCompany": False, "salaryLower": 0, "subwayLineName": "", "subwayStation": ""} 複製代碼
其中,咱們只須要關注 keyword,pageNo,pageSize字段,分別表明搜索什麼職位,搜索第幾頁,每頁搜多少條。markdown
有了這個信息咱們就能夠經過程序來請求不一樣的職位數據,同時爲了獲取職位更詳細的信息咱們還能夠查找獲取職位詳情頁的接口,方式與此相似,這裏就再也不贅述了。請求職位的代碼以下app
def get_data(self): for city in self.cities_conf: for position in self.positions_conf: self.position_search_body['keyword'] = position self.position_search_body['city'] = city pageNo = 1 has_more = 1 while has_more: try: self.position_search_body['pageNo'] = pageNo url = 'https://gate.lagou.com/v1/entry/positionsearch/searchPosition' res = requests.post(url, data=json.dumps(self.position_search_body), headers=self.headers) print('成功爬取%s市-%s職位的第%d頁數據!' % (city, position, pageNo)) item = {'city': city, 'pType': position} print(res.json()) positionCardVos = res.json()['content']['positionCardVos'] self._parse_record(positionCardVos, item) pageNo += 1 if positionCardVos is None or len(positionCardVos) < 15: has_more = 0 time.sleep(random.random() * 5) except Exception as e: msg = '連接訪問不成功,正在重試!Exception: %s' % e print(msg) time.sleep((1 + random.random()) * 10)複製代碼
變量 position 表明不一樣的職位,這裏請求的時候會加隨機停留時間,目的爲了防止請求過於平凡。咱們抓去別人的數據應該注意這一點,不能惡意爬別人的數據。應該模擬得更像普通人同樣去請求數據,若是請求過於頻繁致使別人服務出現問題那真實罪大惡極。
_parse_record 方法是解析請求的數據,並存入mongo。首先解析數據沒什麼好說的,就是解析json而已。簡單說下爲何存入mongo,第一,解析的json數據,mongo存儲就是用json格式,讀取和寫入很是方便;第二,mongo不用提早設計表Schema,對咱們這種臨時性和不肯定性的分析帶來方便;第三,mongo能夠存儲海量的數據;第四,mongo會緩存熱點數據,咱們在後續分析時候讀取會很是快。
_parse_record 方法代碼以下,爲了不囉嗦,我只保留部分字段的解析,其餘的代碼能夠下載詳細代碼來看
def _parse_record(self, data, item): if data: for position in data: item['pId'] = position.get('positionId') item['_id'] = '%s_%s_%d' % (item['city'], item['pType'], item['pId']) # ... 省略 try: position_detail_res = requests.get(self.position_detail_url % item['pId'] , timeout=20, headers=self.headers) # 請求詳情頁的數據 position_content = position_detail_res.json()['content'] item['pAdvantage'] = position_content.get('positionAdvantage') # ...省略 time.sleep(random.random() * 2) except Exception as e: msg = '抓去職位%d詳情頁失敗, Exception: %s' % (item['pId'], e) print(msg) self.db['positions'].update_one({'_id': item['_id']}, {'$set': item}, upsert=True) msg = '成功保存數據:{}!'.format(item) print(msg)複製代碼
能夠看到方法中還請求了職位詳情數據來豐富每一條數據的維度。
抓取數據後下面就是分析了,主要用pandas進行統計和畫圖。因爲代碼是用jupyter寫的,這裏不方便貼,因此我直接貼結論,感興趣的朋友能夠自行查看詳細代碼。
一、哪一個城市目前招聘的崗位多
能夠看到,目前北京招聘的崗位最多,其次是上海和深圳,廣州是最少的。
二、每一個城市各崗位的需求量
北上廣深4個城市目前招聘較多的崗位主要是後端-Java、前端、AI和測試。
三、各崗位的平均薪資狀況
AI崗位的薪資最高,平均每月30k以上;其次是大數據崗位,平均每月26k左右,iOS的平均薪資比Android稍微高一些。另外,目前的前端崗位平均薪資偏低。
四、幾年工做經驗比較吃香
以北京招聘數據爲例,目前招聘的各崗位都是以3-5年工做經驗爲主,1-3年經驗的需求量不大。因此,這裏也要提醒職場新人,不要輕易跳槽。
其餘城市的分佈狀況與北京相似,這裏就不貼圖了。
五、什麼學歷比較吃香
以北京爲例,目前招聘的崗位除了AI須要很多的碩士甚至博士外,其餘崗位以本科學歷爲主。
其餘城市分佈與北京相似。
六、什麼規模公司對崗位需求大
北京
廣州
能夠看到,北京招聘的企業主要是2000人以上規模的大公司,上海和深圳的分佈與北京相似。而廣州在AI、前端和後端-Java幾個崗位的招聘主要以50-1000人的中等規模公司爲主。
七、HR什麼時間段更活躍
以北京爲例,各崗位的HR大部分在下午活躍,因此你們能夠將簡歷的投遞時間選在下午。
其餘城市分佈與北京相似。
八、崗位的職責和要求
限於篇幅,我只跑了AI、後端-Java和前端這3個崗位的數據,以詞雲的形式展示
但願此次分析能對你有用,歡迎公衆號「渡碼」,回覆關鍵字 「職位」 便可獲取本次分析的源碼。