反反爬之python爬蟲實例加分析過程

如何突破常規的反爬限制

今天要記錄的這個爬蟲是我到新工作的第5天接的一個需求,也是我從Java轉Python的第5天寫的一個爬蟲腳本。這個還有腳本有很多可以完善的地方,但也有一些值得參考的地方,下面進行詳細的介紹。

目標網站和爬取素材

目標網站:拍信網 https://www.paixin.com/ (如有冒犯之處,敬請諒解)
爬取素材:各種圖片(在搜索欄中輸入關鍵字,進行查詢得到圖片)

分析過程

怎樣找到目標的url?
首先在搜索欄中輸入關鍵字,進入結果頁面,F12打開谷歌開發者工具,選擇中network面板,刷新頁面;
在選擇xhr(xmlHttpRequest)
圖1
在這裏插入圖片描述

圖2
在這裏插入圖片描述

圖3
在這裏插入圖片描述

分析圖3,根據裏面的請求可知"…search?page=XXX…“請求可以獲取圖片描述和地址以及其他信息,所以該請求就是我們要找的目標url。注意該請求是一個異步請求,返回的數據是json格式的數據。這裏其實有一個坑,看圖2,我從第1頁開始翻頁,翻到第4頁正常來說應該是發送4個請求才對,但是這裏面卻有6個”…search?page=XXX…"請求,且每翻一頁還有“…search_list…”這樣的請求,這是怎麼回事呢?看看這些請求有沒有返回數據,嘗試着在瀏覽器地址欄中發送一下看有什麼結果,綜合分析對比即可發現正確的URL。其實這裏面的一些無用的請求是故意用來迷惑我們的雙眼的,這也是網站的反爬手段之一。

然後我們就可以僞造請求了,剛開始時我在請求頭裏面就寫了一個User-Agent,然後發送請求看一下能否返回數據,結果請求失敗,沒有任何數據返回,然後我又仔細的看了一下Request Headers,裏面的信息的信息很多,我猜測應該是請求頭裏面缺少信息,所以服務器拒絕了請求,既然這樣那就把這些信息放在請求頭裏面,這麼多都需要放嗎?它們分別代表的是什麼意思呢?
headers中的每一項的意義

headers信息中這個referer代表的是referer防盜鏈,是一種常見的反爬手段,指的是該鏈接請求的來源頁面
就這樣我又運行修改後的程序,結果還是沒有返回結果,這到底是怎麼回事?一定是漏掉了什麼,繼續查看檢查了一下headers裏面的信息,發現headers下面有一個Request Playload裏面還有一些參數,那這個Request Playload是什麼呢?
request playload詳解
於是把request playload裏面的數據帶上,發送請求成功返回數據,至此這個爬蟲的難點全部解決。

代碼

分析完了,就直接上代碼吧。

import json
import urllib
import jsonpath
import requests

#拍信創意

def getBlackman(startPage,endPage,path):
    header = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
        'Accept': 'application/json, text/plain, */*', 'Accept - Encoding': 'gzip, deflate, br',
        'Accept - Language': 'zh - CN, zh;q = 0.9', 'Connection': 'keep-alive', 'Content-Length': '41',
        'Content-Type': 'application/json;charset=UTF-8',
        'Host': 'api2.paixin.com', 'Origin': 'https://v.paixin.com',
        'Referer': 'https://v.paixin.com/media/photo/standard/%E9%BB%91%E4%BA%BA%E5%A4%B4%E5%83%8F/2',
        }
    requests.packages.urllib3.disable_warnings()   #禁用https安全證書的驗證
    playloadData = {
        'searchQuery':'三明治',
        'type': '6',
        'searchQuery': '三明治',
        'type': '6'
    }
    for num in range(startPage,(endPage+1)):
        images = requests.post('https://api2.paixin.com/medias/b/search?page=' + str((num-1)) + '&size=80',
                               data=json.dumps(playloadData), headers=header, verify=False,timeout=5)  
  #data=json.dumps(playloadData) 將dict轉化爲str格式
        jsonObjs = json.loads(images.text)
        # print(jsonObjs)
        images = jsonpath.jsonpath(jsonObjs, '$..image')
        i = 1
        for image_url in images:
            try:
                print('*' * 10 + '正在下載第' + str((num - 1) * 80 + i) + '張圖片' + '*' * 10)
                res=urllib.request.urlopen(image_url,timeout=5).read()
                with open(path + '拍信網第'+str((num-1)*80+i) + '張.jpg','wb') as file:
                    file.write(res)
                    file.close()
            except Exception as e:
                print('第'+str((num-1)*80+i)+'張圖片下載出錯,錯誤信息如下:')
                print(' '*10+str(e))
                print('')
                continue
            finally:
                i += 1

    print('*'*15+'下載完成'+'*'*15)

# def save_image(url,path):
#     try:
#         res=urllib.request.urlopen(url,timeout=5).read()

if __name__ == '__main__':
    getBlackman(1, 16, 'd:/download/拍信/三明治/')  # 1頁80張,getBlackman(開始頁,結束頁,圖片存儲路徑)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章