1. 程式人生 > >Python 爬蟲入門-爬取拉勾網實戰

Python 爬蟲入門-爬取拉勾網實戰

這幾天學習了 python 爬蟲的入門知識,也遇到很多坑,開個貼記錄一下

基本原理

Python 爬蟲基本要具備以下功能:(參考此回答

  1. 向伺服器傳送請求,伺服器響應你的請求。(你可能需要了解:網頁的基本知識)
  2. 從抓取到的網頁中提取出需要的資料。(你可能需要了解:正則表示式Beautifulsoup
  3. 儲存資料並繼續爬取下一個網站。

當然,有以上功能還是不夠的,你還需要與網站反爬策略鬥智鬥勇:(參考此回答

  1. 構造合理的HTTP請求頭
  2. 設定cookie
  3. 正常的時間訪問路徑
  4. 注意隱含輸入欄位值
  5. 避開蜜罐
  6. 使用遠端伺服器來避免IP封鎖

當然以上我還不怎麼會。

專案實踐

可以通過以下2個專案練手

  1. 豆瓣電影TOP250
    這個專案比較容易,程式碼複製過來,大概理解程式碼的意思,然後跑的過程也比較順利。

  2. 爬取拉勾網頁面1 頁面2 頁面3
    這個專案就比較難了,我也遇到比較多的坑,好在大都解決了。

話不多說,我們開始吧

爬取拉勾網實戰

借用一下@ _知幾 的圖

借用一下@ _知幾 的圖,按 F12 檢視頁面原始碼,在 NETWORK 標籤中可以分析網站的請求響應過程,這裡看到 NETWORK 標籤下 TYPE XHR 裡有 companyAjax.json 和 positionAjax.json (開始我死活找不到positionAjax.json,後來發現是我沒選工作地點),我們所需求的資料可以從中提取出來。

以下程式碼是我在 _知己 的程式碼基礎上修改得到的

修改了以下幾處:

  1. 由原來的 python 2 改為 python 3
  2. 匯入 fake_useragent 模組,可以隨機偽造請求頭(使用前需 pip install fake-useragent)
  3. 讀取 companyAjax.json 而不是原來的 positionAjax.json

幾點說明:

  1. ua.random 用於生成隨機請求頭
  2. get_json 函式中的 my_headers、 cookies、 content 等,都可以在瀏覽器 F12 控制檯中找到
  3. 目前爬取了幾頁後就被發現,顯示 {‘success’: False, ‘msg’: ‘您操作太頻繁,請稍後再訪問’, ‘clientIp’: ‘202.* * * * * *’},暫時還沒有解決辦法。
#!/usr/bin/env python
# encoding=utf-8

import json
import requests
import xlwt
import time
from lxml import etree
import random
from fake_useragent import UserAgent
import sys


#獲取儲存職位資訊的json物件,遍歷獲得公司名、福利待遇、工作地點、學歷要求、工作型別、釋出時間、職位名稱、薪資、工作年限
def get_json(url,datas):

    ua = UserAgent()
    my_headers = {
        'User-Agent': ua.random ,
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.6,ja;q=0.4,en;q=0.2',
        'Host': 'www.lagou.com',
        'Origin': 'https://www.lagou.com',
        'Referer': 'https://www.lagou.com/zhaopin/?filterOption=',
    }
    cookies = {
        'Cookie': 'user_trace_token=20170824135842-485287de-8891-11e7-a544-525400f775ce; LGUID=20170824135842-48528e05-8891-11e7-a544-525400f775ce; JSESSIONID=ABAAABAAADEAAFI772FD1B9AABBF0C5553E874B0F860350; _putrc=B95D7C5E94F53DA8; login=true; unick=%E9%83%AD%E5%B2%A9; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=3; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; _gat=1; TG-TRACK-CODE=index_search; SEARCH_ID=f0acbb8b2145433cb8fe7086f23be622; index_location_city=%E5%8C%97%E4%BA%AC; _gid=GA1.2.397092414.1504747009; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1504756944,1504761486,1504783443,1504839029; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1504839719; _ga=GA1.2.1499897355.1503554319; LGSID=20170908105032-7b45520c-9440-11e7-8aae-525400f775ce; LGRID=20170908110159-14c6e1a8-9442-11e7-8ab1-525400f775ce'
    }
    time.sleep(20 + random.randint(0,20))
    content = requests.post(url=url,cookies=cookies,headers=my_headers,data=datas)
    # content.encoding = 'utf-8'
    result = content.json()
    print(result)
    info = result['content']['positionResult']['result']
    # print info
    info_list = []
    for job in info:
        information = []
        information.append(job['positionId']) #崗位對應ID
        information.append(job['companyFullName']) #公司全名
        information.append(job['companyLabelList']) #福利待遇
        information.append(job['district']) #工作地點
        information.append(job['education']) #學歷要求
        information.append(job['firstType']) #工作型別
        information.append(job['formatCreateTime']) #釋出時間
        information.append(job['positionName']) #職位名稱
        information.append(job['salary']) #薪資
        information.append(job['workYear']) #工作年限
        info_list.append(information)
        #將列表物件進行json格式的編碼轉換,其中indent引數設定縮排值為2
        print(json.dumps(info_list,ensure_ascii=False,indent=2))
        print(info_list)
    return info_list


def main():
    page = int(input('輸入抓取頁數:'))
    # kd = raw_input('請輸入你要抓取的職位關鍵字:')
    # city = raw_input('請輸入你要抓取的城市:')
    info_result = []
    title = ['崗位id','公司全名','福利待遇','工作地點','學歷要求','工作型別','釋出時間','職位名稱','薪資','工作年限']
    info_result.append(title)
    for x in range(1,page+1):
        url = 'https://www.lagou.com/jobs/companyAjax.json?px=new&needAddtionalResult=false'
        datas = {
            'first': True,
            'pn': x,
            'kd': '',
            #'city': '上海'
        }
        info = get_json(url,datas)
        info_result = info_result+info
        #建立workbook,即excel
        workbook = xlwt.Workbook(encoding='utf-8')
        #建立表,第二引數用於確認同一個cell單元是否可以重設值
        worksheet = workbook.add_sheet('lagouzp',cell_overwrite_ok=True)
        for i, row in enumerate(info_result):
            # print row
            for j,col in enumerate(row):
                # print col
                worksheet.write(i,j,col)
            workbook.save('C:\\Users\\jared\\Desktop\\lagouzp.xls')

if __name__ == '__main__':
    main()