前言
為了了解跟python數據分析有關行業的信息,大概地了解一下對這個行業的要求以及薪資狀況,我決定從網上獲取信息并進行分析。既然想要分析就必須要有數據,于是我選擇了拉勾,冒著危險深入內部,從他們那里得到了信息。不得不說,拉勾的反爬技術還挺厲害的,稍后再說明。話不多說,直接開始。
一、明確目的
每次爬蟲都要有明確的目的,剛接觸隨便找東西試水的除外。我想要知道的是python數據分析的要求以及薪資狀況,因此,薪資、學歷、工作經驗以及一些任職要求就是我的目的。
既然明確了目的,我們就要看一下它們在什么位置,所以我們打開瀏覽器,尋找目標。像拉勾這種網站他們的信息一般都是通過ajax加載的,而且在輸入“python數據分析”敲擊回車之后跳轉的頁面,招聘信息不是一開始就顯示出來的,通過點擊頁碼也只是招聘信息在變化甚至連network都沒多大變化,可以大膽猜測他是通過post請求的,所以我們只關注post請求以及xhr文件,很快就發現了我們要的東西。
點擊preview可見詳細信息以json形式保存著,其中‘salary'、‘workyear'、‘education'、‘positionid'(招聘信息詳情頁有關的id)是我們要的。再觀察一下它的form data,其中kd=關鍵字,pn=pagenum(頁碼)這是我們請求的時候要帶上的參數。另外我們要注意請求頭的referer參數,待會兒要用。知道了目標之后,爬起來!
二、開始爬蟲
先設置請求頭headers,把平時用的user-agent帶上,再把formdata也帶上,用requests庫直接requests.post(url, headers=headers, data=formdata)
,然后就開始報錯了: {"status":false,"msg":"您操作太頻繁,請稍后再訪問","clientip":"......","state":2402}
。
解決這個問題的關鍵在于,了解拉勾的反爬機制:在進入python數據分析招聘頁之前,我們要在主頁,不妨叫它start_url輸入關鍵字跳轉。在這個過程中,服務器會傳回來一個cookies,如果帶著這個cookies請求的話我們就可以得到要的東西,所以要先請求start_url獲取cookies在請求目標url,而且在請求目標地址的話還要帶上referer這個請求頭參數,referer的含義大概是這樣:告訴服務器我是從哪個頁面鏈接過來的,服務器基此可以獲得一些信息用于處理。另外,睡眠時間也要設置的長一點,不然很容易被封。知道了反爬機制之后,話不多說,直接上代碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
''' @author: max_lyu create time: 2019/4/1 url: https://github.com/maxlyu/lagou_analyze ''' # 請求起始 url 返回 cookies def get_start_url( self ): session = requests.session() session.get( self .start_url, headers = self .headers, timeout = 3 ) cookies = session.cookies return cookies # 將返回的 cookies 一起 post 給 target_url 并獲取數據 def post_target_url( self ): cookies = self .get_start_url() pn = 1 for pg in range ( 30 ): formdata = { 'first' : 'false' , 'pn' : pn, 'kd' : 'python數據分析' } pn + = 1 response = requests.post( self .target_url, data = formdata, cookies = cookies, headers = self .headers, timeout = 3 ) self .parse(response) time.sleep( 60 ) # 拉勾的反扒技術比較強,短睡眠時間會被封 # 解析 response,獲取 items def parse( self , response): print (response) items = [] print (response.text) data = json.loads(response.text)[ 'content' ][ 'positionresult' ][ 'result' ] if len (data): for i in range ( len (data)): positionid = data[i][ 'positionid' ] education = data[i][ 'education' ] workyear = data[i][ 'workyear' ] salary = data[i][ 'salary' ] list = [positionid, education, workyear, salary] items.append( list ) self .save_data(items) time.sleep( 1.3 ) |
其中save_data(items)是保存文件,我是保存在csv文件。篇幅有限,這里就不展示了。
三、獲取招聘詳情
上面說了positionid 是為了獲取詳情頁,詳情頁里面有要的任職要求。這個要獲取就相對容易了,不過文本的處理并沒有很簡單,我只能通過“要求”這兩個字獲取任職要求(雖然有的為任職技能啥的,就這樣進行取舍了)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
''' @author: max_lyu create time: 2019/4/1 url: https://github.com/maxlyu/lagou_analyze ''' def get_url(): urls = [] with open ( "analyst.csv" , 'r' , newline = '') as file : # 讀取文件 reader = csv.reader( file ) for row in reader: # 根據 positionid 補全 url if row[ 0 ] ! = "id" : url = "https://www.lagou.com/jobs/{}.html" . format (row[ 0 ]) urls.append(url) file .close() return urls # 獲取詳細信息 def get_info(): urls = get_url() length = len (urls) for url in urls: print (url) description = '' print (length) response = requests.get(url, headers = headers) response.encoding = 'utf-8' content = etree.html(response.text) detail = content.xpath( '//*[@id="job_detail"]/dd[2]/div/p/text()' ) print (detail) for i in range ( 1 , len (detail)): if '要求' in detail[i - 1 ]: for j in range (i, len (detail)): detail[j] = detail[j].replace( '\xa0' , '') detail[j] = re.sub( '[、;;.0-9。]' , '', detail[j]) description = description + detail[j] + '/' print (description) write_file(description) length - = 1 time.sleep( 3 ) |
四、成果與展示
到這里,爬取的任務就結束了,源碼地址:https://github.com/maxlyu/lagou_analyze。獲得數據之后就是小小地分析一下了,這個下次再總結。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。
原文鏈接:https://www.cnblogs.com/lyuzt/p/10636501.html