爬取拉勾網爬蟲工程師職位

最近真的好累啊,心累,很多事想快點做完,但是每個人都有拖延癥,疊加到我這一層都不知道拖延到什么時候了。好多事總想著要是可以我自己全部搞定就好了。為什么有些人就是不能早定啟動計劃呢?心累。


藍瘦香菇~喵

寫代碼吧,這是唯一能“消遣”的方式了。
看到傳智播客課件上有給學員留一些爬蟲作業,嘿嘿,自己決定做做看。
今天做 “爬取拉勾網爬蟲工程師職位”。

更新:元旦快樂!元旦終于能過個雙休,好好陪姐姐和麻麻,順便學學爬蟲吧()

第一次爬動態頁面,一時不知道該怎么下手,好在拉勾是爬蟲工程師常用來練手的地方,攻略挺多,哈哈。整體思路如下:

  1. 構造并獲取請求
  2. 解析所需要的數據
  3. 以Excel形式保存在本地。

1.構造并獲取請求:
由于拉勾采用異步加載技術,之前用的很簡單的獲取靜態頁面的方式就不行了。需要通過抓包獲得數據包,再從數據包里解析所需要的數據。

打開拉勾網,查找關鍵字“爬蟲工程師”,打開谷歌瀏覽器賢者模式-network,如下:


image.png

監聽器中看到的數據有很多,css, png, js......我們需要的數據包均不在以上列出來的類型里,我們的關注點主要是在xhr類型的文件中,關于什么是xhr本渣也不是很懂,只知道它是Ajax對象,而Ajax是目前前端廣泛應用的一種技術,關于Ajax的更多信息暫不做詳細了解。
過濾xhr類型的數據流,我們可以直接選擇 >>>谷歌瀏覽器-Network-XHR獲取:


image.png

這就獲得了所有的XHR文件,這時候我們看看獲得的是不是需要的數據,逐個點開-Preview:
image.png

這里我點開第一個數據包,其他的類似操作。可以看到,這個數據包里確實包含我們需要的信息,那問題來了,我要如何才能拿到這個數據包呢?

一開始我哧吭哧吭地采用之前很簡單的傳入UA, Cookies, 然后

requests.get(url, header = headers, cookies = cookies)

甚至連瀏覽器的監聽都沒看,這樣拿到的只是拉勾網首頁的靜態頁面上的數據,根本拿不到想要的數據。于是仔細看瀏覽器的監聽,之前抓到的XHR數據包的Headers如下:


image.png

關注點有兩個:
Request URL和Request Method,這里對應可以知道獲取這個數據包的鏈接以及方法。

繼續往下看:


image.png

form data是我們發起post時必要的參數
然后我又哧吭哧吭地開始碼代碼了:

# -*- coding: utf-8 -*-
import requests

def get_js(page, job_name):
url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E5%B9%BF%E5%B7%9E&needAddtionalResult=false&isSchoolJob=0'

headers = {
    'Cookie': "user_trace_token=20171218074035-ade4d2dc-e383-11e7-9def-525400f775ce; LGUID=20171218074035-ade4d6be-e383-11e7-9def-525400f775ce; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=0; JSESSIONID=ABAAABAACBHABBIC9F4C6647BF37CF4EDC0DB33759D67C9; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; _putrc=21717327F1B053B4; _gid=GA1.2.1846682322.1514773610; _ga=GA1.2.2062218679.1513554042; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1513554041,1514544070,1514608259,1514773610; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1514773651; LGSID=20180101102652-3a420853-ee9b-11e7-b956-525400f775ce; LGRID=20180101102732-52342eb9-ee9b-11e7-9fc4-5254005c3644; SEARCH_ID=7275bd67bfd7481fb9033dab8abc11f3; index_location_city=%E5%B9%BF%E5%B7%9E",
    'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
        }
data = {'first': 'true',
        'pn': page,
        'kd': job_name
        }
response = requests.post(url, data, headers=headers)
print(response.text)

結果:


image.png

其實在瀏覽器中直接輸入網址:

url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E5%B9%BF%E5%B7%9E&needAddtionalResult=false&isSchoolJob=0'

結果:


image.png

也是一樣的。小白如我黑人問號臉了很久,開始找答案,偶然間看到XX培訓機構的視頻中提到過的一個點,瀏覽器header中referer防止重定向,其實自己之前也聽到過referer,它是規定了當前的鏈接只能由某一個鏈接轉到,不能直接跳轉;不過到這里,才切實體會到其在反爬中的作用。

至此,整體的獲取數據的代碼如下:

# -*- coding: utf-8 -*-
# https://www.lagou.com/jobs/list_python?px=default&city=%E5%8C%97%E4%BA%AC#filterBox

import requests,json,xlwt

def get_js(page, job_name):
    url = 'https://www.lagou.com/jobs/positionAjax.json?city=%E5%B9%BF%E5%B7%9E&needAddtionalResult=false&isSchoolJob=0'

    headers = {
        'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
        'Accept': "application/json, text/javascript, */*; q=0.01",
        'Accept-Encoding': "gzip, deflate, br",
        'Accept-Language': "zh-CN,zh;q=0.9",
        'Connection': "keep-alive",
        'Content-Length': "82",
        'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
        'Cookie': "user_trace_token=20171218074035-ade4d2dc-e383-11e7-9def-525400f775ce; LGUID=20171218074035-ade4d6be-e383-11e7-9def-525400f775ce; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=0; JSESSIONID=ABAAABAACBHABBIC9F4C6647BF37CF4EDC0DB33759D67C9; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; _putrc=21717327F1B053B4; _gid=GA1.2.1846682322.1514773610; _ga=GA1.2.2062218679.1513554042; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1513554041,1514544070,1514608259,1514773610; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1514773651; LGSID=20180101102652-3a420853-ee9b-11e7-b956-525400f775ce; LGRID=20180101102732-52342eb9-ee9b-11e7-9fc4-5254005c3644; SEARCH_ID=7275bd67bfd7481fb9033dab8abc11f3; index_location_city=%E5%B9%BF%E5%B7%9E",
        'Host': "www.lagou.com",
        'Origin': "https://www.lagou.com",
        'Referer': "https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E7%88%AC%E8%99%AB%E5%B7%A5%E7%A8%8B%E5%B8%88?labelWords=&fromSearch=true&suginput=",
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
        'X-Anit-Forge-Code': "0",
        'X-Anit-Forge-Token': "None",
        'X-Requested-With': "XMLHttpRequest",
        'Cache-Control': "no-cache",
        'Postman-Token': "2311c5f1-5e34-dc58-d976-e26148708846"
        }
    data = {'first': 'true',
            'pn': page,
            'kd': job_name
            }
    response = requests.post(url, data, headers=headers)

2.解析數據
剛剛我們從拉勾上獲取了響應的數據包,這里我們還是要回去看瀏覽器中捕捉到的信息,谷歌瀏覽器-NETWORK-XHR-第一個XHR包-Preview:


image.png

我們要獲得的數據,對應的路徑為:content-positionResult-result-0(一直到14)
這里0-14可以點開看,就是每個職位的具體信息:


image.png

這些json類型的數據,解析起來很方便,類似于鍵值對的形式,只要我們取其中的鍵就能獲取值。不過首先我們需要對上面get_js(page, job_name)函數做點補充,讓它直接拿到json數據。直接上代碼吧
def parse_js(json_info):
    #定義一個空列表,用以存放我們想要提取的數據
    info_list = []
    for info in json_info:
        #將要的數據通通放到空列表中
        info_list.append(info['companyFullName'])
        info_list.append(info['companyShortName'])
        info_list.append(info['companyId'])
        info_list.append(info['positionName'])
        info_list.append(info['salary'])
        info_list.append(info['workYear'])
        info_list.append(info['education'])
        info_list.append(info['industryField'])
        info_list.append(info['financeStage'])
        info_list.append(info['companySize'])
        info_list.append(info['city'])
    return info_list

然后將數據保存下來就行了。代碼如下:

def main():

    # 先定義一個空列表,這個列表才是我們真正會寫進Excel的列表
    real_list = []
    # 這里寫入 Excel 我用 xlwt 這個庫
    book = xlwt.Workbook()
    sheet1 = book.add_sheet('crwalerposition.xls', cell_overwrite_ok=True)

    # 先做個表頭
    proformlist = ['公司全稱', '公司簡稱', '公司代號', '職位名稱', '薪水區間', '工作年限', '教育程度', '行業性質', '目前狀況', '公司規模', '上班地點']
    j = 0
    for pro in proformlist:
        sheet1.write(0, j, pro)
        j += 1

    i_list = []
    page = 1
    while page < 26:
        i_list = i_list + parse_js(get_js(str(page), "爬蟲工程師"))
        print("得到第%r頁數據" % page)
        page += 1
        # time.sleep(5)
        # print(i_list)

    for k in range(0, len(i_list), 11):
        # 將大列表以11為切割的單位,切割成小列表,方便后面操作。這里感覺有點吃力不討好了。。。
        new_list = i_list[k: k + 11]
        real_list.append(new_list)

    m = 1
    for list in real_list:
        n = 0
        for info in list:
            sheet1.write(m, n, info)
            n += 1
        print("第%r家公司數據錄入完畢" %m )
        m += 1
    print("搞定收工!" )
    book.save('python_job_info_in_all.xls')

main()

關于保存,我摸了很久。一開始的思路是,將"保存"這件事封裝成一個函數,這樣,獲取,解析和保存都能單獨作為一個函數,再編寫一個main函數,用for循環遍歷所有的20多個頁面將,并對以上函數調用就OK。然而當我執行代碼的時候,數據總是只能拿到兩頁數據而已。

為什么只能拿到兩頁數據?明明有二十幾頁的呀?這時候新手的不自信就出現了:肯定是我的代碼出現了某種問題,而且這個問題應該在外人看來很簡單。我仔細把重頭代碼看幾遍,試著將解析的列表打印出來看,顯示確實只有那么多數據,排除是寫入文件的問題。

那就是獲取數據出現問題咯?被ban了?爬取太快?可是我每一次重新跑代碼都可以得到數據呀,數據也不多不少就只有那么多,兩頁。我用了隨機ua, time.sleep,差點就上代理ip了,結果還是沒,卵,用!!還是偶然的機會,再回去看拉勾網的時候才注意到,我爬的數據和我看的頁面根本不一樣!!尼瑪坑爹,不知道什么時候手抖把查詢城市選為不限了,而一開始我只打算爬取廣州地區的數據的!!廣州本地的爬蟲工程師職位確實只有兩頁。。。。。。(可憐== 本來自己就菜,工作機會還這么少。。。)

下面是全部完整代碼:

# -*- coding: utf-8 -*-
# https://www.lagou.com/jobs/list_python?px=default&city=%E5%8C%97%E4%BA%AC#filterBox

import requests,json,xlwt
import time,random

def get_js(page, job_name):
    url = 'https://www.lagou.com/jobs/positionAjax.json?px=default&needAddtionalResult=false&isSchoolJob=0'
    #隨機ua列表
    UA_list = ["Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
               "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
               "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
               "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6"
               ]
    UA = random.choice(UA_list)

    #構造請求參數
    headers = {
        'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
        'Accept': "application/json, text/javascript, */*; q=0.01",
        'Accept-Encoding': "gzip, deflate, br",
        'Accept-Language': "zh-CN,zh;q=0.9",
        'Connection': "keep-alive",
        'Content-Length': "82",
        'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
        'Cookie': "user_trace_token=20171218074035-ade4d2dc-e383-11e7-9def-525400f775ce; LGUID=20171218074035-ade4d6be-e383-11e7-9def-525400f775ce; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=0; JSESSIONID=ABAAABAACBHABBIC9F4C6647BF37CF4EDC0DB33759D67C9; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; _putrc=21717327F1B053B4; _gid=GA1.2.1846682322.1514773610; _ga=GA1.2.2062218679.1513554042; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1513554041,1514544070,1514608259,1514773610; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1514773651; LGSID=20180101102652-3a420853-ee9b-11e7-b956-525400f775ce; LGRID=20180101102732-52342eb9-ee9b-11e7-9fc4-5254005c3644; SEARCH_ID=7275bd67bfd7481fb9033dab8abc11f3; index_location_city=%E5%B9%BF%E5%B7%9E",
        'Host': "www.lagou.com",
        'Origin': "https://www.lagou.com",
        'Referer': "https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E7%88%AC%E8%99%AB%E5%B7%A5%E7%A8%8B%E5%B8%88?labelWords=&fromSearch=true&suginput=",
        'User-Agent': UA,
        'X-Anit-Forge-Code': "0",
        'X-Anit-Forge-Token': "None",
        'X-Requested-With': "XMLHttpRequest",
        'Cache-Control': "no-cache",
        'Postman-Token': "2311c5f1-5e34-dc58-d976-e26148708846"
        }
    data = {'first': 'true',
            'pn': page,
            'kd': job_name
            }
    response = requests.post(url, data, headers=headers)
    json_info = response.json()['content']['positionResult']['result']
    return json_info #此處return的是一個列表類型

def parse_js(json_info):
    #定義一個空列表,用以存放我們想要提取的數據
    info_list = []
    for info in json_info:
        #將要的數據通通放到空列表中
        info_list.append(info['companyFullName'])
        info_list.append(info['companyShortName'])
        info_list.append(info['companyId'])
        info_list.append(info['positionName'])
        info_list.append(info['salary'])
        info_list.append(info['workYear'])
        info_list.append(info['education'])
        info_list.append(info['industryField'])
        info_list.append(info['financeStage'])
        info_list.append(info['companySize'])
        info_list.append(info['city'])
    return info_list

def main():

    # 先定義一個空列表,這個列表才是我們真正會寫進Excel的列表
    real_list = []
    # 這里寫入 Excel 我用 xlwt 這個庫
    book = xlwt.Workbook()
    sheet1 = book.add_sheet('crwalerposition.xls', cell_overwrite_ok=True)

    # 先做個表頭
    proformlist = ['公司全稱', '公司簡稱', '公司代號', '職位名稱', '薪水區間', '工作年限', '教育程度', '行業性質', '目前狀況', '公司規模', '上班地點']
    j = 0
    for pro in proformlist:
        sheet1.write(0, j, pro)
        j += 1

    i_list = []
    page = 1
    while page < 26:
        i_list = i_list + parse_js(get_js(str(page), "爬蟲工程師"))
        print("得到第%r頁數據" % page)
        page += 1
        # time.sleep(5)
    # print(i_list)

    for k in range(0, len(i_list), 11):
        # 將大列表以11為切割的單位,切割成小列表,方便后面操作。這里感覺有點吃力不討好了。。。
        new_list = i_list[k: k + 11]
        real_list.append(new_list)

    m = 1
    for list in real_list:
        n = 0
        for info in list:
            sheet1.write(m, n, info)
            n += 1
        print("第%r家公司數據錄入完畢" %m )
        m += 1
    print("搞定收工!" )
    book.save('python_job_info_in_all.xls')

main()
成果展示
代碼結束界面

總結:
1.異步請求,抓包要學會刪選。今天試著抓一些淘寶的評論,哇,那數據簡直嘩嘩的,都不知道自己要的數據在哪個數據包里。告訴自己,學會抓包、學會用抓包工具!

2.簡單的反爬策略:UA, 代理,延時。其他的策略有待繼續學習。

3.把淘寶京東爬一下,就該學學如何提高效率了。

4.scrapy ,scrapy,scrapy,scrapy

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1 前言 作為一名合格的數據分析師,其完整的技術知識體系必須貫穿數據獲取、數據存儲、數據提取、數據分析、數據挖掘、...
    whenif閱讀 18,103評論 45 523
  • 1.針對最近的爆款文《就算老公一毛錢股份都沒拿到,在我心里,他依然是最牛逼的創業者》,用不超過三句,說說要不要抓熱...
    珊_76f8閱讀 307評論 0 0
  • 開會那些細碎而美好的存在 開會,大都市生活圈里各大機構的最基本元素。 欲望,也是我們在都市里生存的基本元素。...
    陳東紅先生閱讀 506評論 1 2
  • 一聲嘆息吹皺了記憶 泛黃書信舊香四溢 縈繞鼻尖揮之不去的秘密 路燈下的吻禮 輾轉千年把愛恨翻洗 從未細細看過你 尤...
    陌諾流年閱讀 416評論 15 30
  • 久經烈日燒灼的重慶終于在九月放涼,微風夾雜著細雨的黃昏,空氣中彌漫著久違的絲絲涼意。霓虹燈照耀出風和雨的形狀,就像...
    是卷卷兒哇閱讀 709評論 0 2