1. 程式人生 > 其它 >python之seleniumwire獲取請求頭引數

python之seleniumwire獲取請求頭引數

selenium-wire擴充套件了 Selenium 的 Python 繫結,讓您可以訪問瀏覽器發出的底層請求。 您編寫程式碼的方式與使用 Selenium 的方式相同,但您可以獲得額外的 API 來檢查請求和響應並動態更改它們

一:簡介

selenium是爬蟲常用的手段之一,由於是使用瀏覽器驅動模擬手動操作,所以只要掌握一些元素的基本定位就很容易上手。
但是經常會遇到的問題我覺得至少有兩點:

每次啟動的瀏覽器都是一個全新的瀏覽器,不存在任何的快取,換句話說如果網站需要登入則每次啟動都需要登入,需要郵件驗證碼的網站就更難受了。
現在大多數的網站都採用前後端分離+ajax技術,分析畫面元素固然是可以的,但是如果能夠獲取瀏覽器後臺的ajax資料,那簡直是事半功倍。
本次主要討論的就是這兩個問題,在之前我總結過一些相關的坑,包括瀏覽器的cookie操作、performance獲取瀏覽器後臺日誌資料以及瀏覽器的代理認證框的處理問題,這也算是對之前的一次補充。

二:Selenium利用本地瀏覽器進行測試

是的,你沒看錯。由於驅動的是本地瀏覽器,本地瀏覽器有快取,所以完美避免了瀏覽器的cookie問題。而且親測,這種方式還可以直接解析瀏覽器當前網頁,不需要啟動新的瀏覽器,也就是說你可以預先登入到目標網站再執行程式。

1、右鍵谷歌瀏覽器快捷方式->屬性,在路徑上追加引數 --remote-debugging-port=9222

2、雙擊開啟瀏覽器
3、selenium遠端模式連線瀏覽器並進行操作,這裡測試控制瀏覽器開啟百度。

from selenium import webdriver
from selenium.webdriver.chrome.options import
Options chrome_options = Options() chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222") driver = webdriver.Chrome(options=chrome_options) driver.get("https://www.baidu.com")

這樣就已經可以了,跟正常的selenium操作沒有任何區別。

二、Selenium-wire獲取後臺資料

(一)selenium-wire安裝

pip install selenium-wire

例項1:

import time
from seleniumwire import webdriver

# Create a new instance of the Chrome driver
driver = webdriver.Chrome()
# Go to the YouTube homepage.
driver.get('http://tool.liumingye.cn/music/?page=audioPage&type=migu&name=%E6%8A%96%E9%9F%B3')
time.sleep(5)
# Access requests via the `requests` attribute
for request in driver.requests:
    if request.response:
        if request.path == "/m/api/search":
            print(request.response.body.decode("utf-8"))
driver.quit()

封裝後的driver會有requests這樣一個物件,可以發跟瀏覽器開發者工具的Network進行類比,請求的返回值儲存在response.body中。
通過request.path過濾出我們想要的請求,然後獲取response.body即可。

執行結果如下:

{"code":200,"data":{"list":[{"name":"把孤獨當作晚餐(抖音版)","artist":"畫詞戲子","cover":"http:\/\/d.musicapp.migu.cn\/prod\/file-service\/file-down\/8121e8df41a5c12f48b69aea89b71dab\/0f0e94be13d0d18b4cd0f53996e0023b\/18bde3d3d5415eba88115dab279a8b4e","lrc":"http:\/\/59.110.45.28\/m\/api\/lrc\/migu\/id\/f8ceFzdyYgzcjzn5SuaHgUIARghxmB8jGoQIXczI3sOpkObywQMI-l8gtQ81JkoAm91NAZiVFqn2sz-LM7vsi7ycKuefN3JDZWHyMeVFO0toeLCawtmuafH-7iXPvu_lMWxYPkpA6-0-iyFzbqnwdaUWemgw6Ih2tmUPWXXHuA","url_m4a":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=LQ&netType=00&copyrightId=0&contentId=600913000005364995&resourceType=2&channel=0","url_128":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=PQ&netType=00&copyrightId=0&contentId=600913000005364995&resourceType=2&channel=0","url_320":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=HQ&netType=00&copyrightId=0&contentId=600913000005364995&resourceType=2&channel=0","url_flac":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=SQ&netType=00&copyrightId=0&contentId=600913000005364995&resourceType=E&channel=0","url":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=LQ&netType=00&copyrightId=0&contentId=600913000005364995&resourceType=2&channel=0"},{"name":"你走(抖音版)","artist":"鬆緊先生","cover":"http:\/\/d.musicapp.migu.cn\/prod\/file-service\/file-down\/b1899d500dda5db2da11df3efc89cba6\/d6ac70e448ff3cd5d545cf44d0d7a2c0\/c1690b3588064699c3688d676984331f","lrc":"http:\/\/59.110.45.28\/m\/api\/lrc\/migu\/id\/b30fUTX4wkz-oVd-f8y9OQ_kKBBi4zY2Aje7_xDOCt_kVgFl9nQjZo9U1oenDZiCAQJ6coUeJiWG7OGE9fc87A-z0llkBxgLJdxlW-_3LXaKxHkh29HDtMkYTExcEk20jfTXt_0BVLYaeBOf0dMAf4b0mFWQ5PQ6g1Bd7tPZ4w","url_m4a":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=LQ&netType=00&copyrightId=0&contentId=600919000000557974&resourceType=2&channel=0","url_128":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=PQ&netType=00&copyrightId=0&contentId=600919000000557974&resourceType=2&channel=0","url_320":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=HQ&netType=00&copyrightId=0&contentId=600919000000557974&resourceType=2&channel=0","url_flac":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=SQ&netType=00&copyrightId=0&contentId=600919000000557974&resourceType=E&channel=0","url":"http:\/\/218.205.239.34\/MIGUM2.0\/v1.0\/content\/sub\/listenSong.do?toneFlag=LQ&netType=00&copyrightId=0&contentId=600919000000557974&resourceType=2&channel=0"}}

例項2:

from seleniumwire import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通過requests屬性訪問請求
for request in driver.requests:
    if request.response:
        print("Url:", request.url)
        print("Code:", request.response.status_code)
        print("Content-Type:", request.response.headers['Content-Type'])

執行結果:

例項3:設定攔截器

可以在某些請求發出前,修改請求的引數或直接阻止請求

import json
from seleniumwire import webdriver

# 設定攔截器
def interceptor(request):
    # 攔截.png,.jpg,.gif結尾的請求
    if request.path.endswith(('.png', '.jpg', '.gif')):
        request.abort()

driver = webdriver.Chrome()
driver.request_interceptor = interceptor
driver.get('https://www.baidu.com')

# 通過requests屬性訪問請求
for request in driver.requests:
    if request.response:
        print("Url:", request.url)
        print("Code:", request.response.status_code)
        print("Content-Type:", request.response.headers['Content-Type'])

新增和修改請求引數

# 設定攔截器
def interceptor(request):
    # 新增請求引數
    params = request.params
    params['foo'] = 'bar'
    request.params = params

    # 修改POST請求正文中的JSON
    if request.method == 'POST' and request.headers['Content-Type'] == 'application/json':
        # 獲取原請求內容
        body = request.body.decode('utf-8')
        data = json.loads(body)
        # 修改要改變的引數
        data['foo'] = 'bar'
        # 將修改好的引數設定回請求
        request.body = json.dumps(data).encode('utf-8')
        # 更新內容長度
        del request.headers['Content-Length']
        request.headers['Content-Length'] = str(len(request.body))