首頁 > 軟體

python反反爬蟲技術限制連續請求時間處理

2022-06-10 18:01:34

前言

一般的反爬措施是在多次請求之間增加隨機的間隔時間,即設定一定的延時。但如果請求後存在快取,就可以省略設定延遲,這樣一定程度地縮短了爬蟲程式的耗時。

下面利用requests_cache實現模擬瀏覽器快取行為來存取網站,具體邏輯如下:存在快取,就直接走,不存在快取,就停一下再走

範例程式碼

用勾子函數根據快取行為設定存取時間

import requests_cacheimport timerequests_cache.install_cache()  
#預設按照瀏覽器的快取進行
requests_cache.clear()
    def make_throttle_hook(timeout=0.1):    
    def hook(response, *args, **kwargs):        
print(response.text)          
# 判斷沒有快取時就新增延時       
    if not getattr(response, 'from_cache', False):               
    print(f'Wait {timeout} s!')               
         time.sleep(timeout)       
         else:               
    print(f'exists cache: {response.from_cache}')       
         return response   
         return hookif __name__ == '__main__':    
    requests_cache.install_cache()    
    requests_cache.clear()   
    session = requests_cache.CachedSession() 
# 建立快取對談    
session.hooks = {'response': make_throttle_hook(2)} 
# 設定勾點函數    
    print('first requests'.center(50,'*'))    
    session.get('http://httpbin.org/get')   
    print('second requests'.center(50,'*'))    
    session.get('http://httpbin.org/get')

有關requests_cache的更多用法,參考下面requests_cache說明

爬蟲相關庫

1. 爬蟲常用的測試網站:httpbin.org

httpbin.org 這個網站能測試 HTTP 請求和響應的各種資訊,比如 cookie、ip、headers 和登入驗證等,且支援 GET、POST 等多種方法,對 web 開發和測試很有幫助。它用 Python + Flask 編寫,是一個開源專案。

2. requests-cache

requests-cache,是 requests 庫的一個擴充套件包,利用它可以非常方便地實現請求的快取,直接得到對應的爬取結果。

作用和使用場景

1.在爬取過程中,它可以根據瀏覽器的快取機制來選擇快取內容。從請求行為上看與瀏覽器更加相似,起到反反爬的效果。

2.另外,還可以自定義快取機制,在爬蟲專案中,優化效能。

requests-cache庫只能對requests的請求實現快取功能,而且requests要以session方式進行請求。單獨的requests.get、requests.post 不能被快取。 

requests

使用方法

安裝: 

$ pip install requests-cache

與普通的程式碼比較

在爬取一個域名下的多個url時,使用requests.session.get或requests.session.post會比單純的requests.get、requests.post更高效。因為它只建立了一個對談,並在上面做多次請求。同時還支援登入資訊cookie等的傳遞。

下面比較一下快取程式碼的寫法 沒有快取的程式碼:

普通的requests session爬取

import requests
import time
start = time.time()
session = requests.Session()
for i in range(10):
    session.get('http://httpbin.org/delay/1')
    print(f'Finished {i + 1} requests')
end = time.time()
print('Cost time', end - start)

該程式碼是存取了httpbin.org網站,該網站會解析delay/1,在1秒後返回。

有快取的程式碼:

帶快取的requests session爬取

import requests_cache #pip install requests_cache
import time
start = time.time()
session = requests_cache.CachedSession('demo_cache')
for i in range(10):
    session.get('http://httpbin.org/delay/1')
    print(f'Finished {i + 1} requests')
end = time.time()
print('Cost time', end - start)

為原有程式碼微創式新增快取功能

只需要新增一句requests_cache.install_cache('demo_cache')即可。

微創式新增快取功能

import requests_cache #pip install requests_cache
requests_cache.install_cache('demo_cache')#demo_cache.sqlite 做快取
import requests
import time
start = time.time()
session = requests.Session()
for i in range(10):
    session.get('http://httpbin.org/delay/1')
    print(f'Finished {i + 1} requests')
end = time.time()
print('Cost time', end - start)

快取的清空和識別

如果需要清空快取,可以呼叫:requests_cache.clear() # 清空快取程式碼

通過res.from_cache可以判斷該值是否是快取值:

import requests_cache
import requests
requests_cache.install_cache() # 設定快取
requests_cache.clear() # 清空快取
url = 'http://httpbin.org/get'
res = requests.get(url)
print(f'cache exists: {res.from_cache}')
# cache exists: False # 不存在快取
res = requests.get(url)
print(f'exists cache: {res.from_cache}')
# exists cache: True # 存在快取

自定義設定快取的形式

requests_cache.install_cache預設的方式是與瀏覽器的快取行為一致的。如果要自定義可以先了解該函數的引數:

requests_cache.install_cache定義

requests_cache.install_cache(    
    cache_name='cache',    
    backend=None,    
    expire_after=None,    
    allowable_codes=(200,),    
    allowable_methods=('GET',),    
    filter_fn=<
function <lambda> at 0x11c927f80>,    
        session_factory=<
        class 'requests_cache.core.CachedSession'>,   
        **backend_options,)

該引數說明如下: - cache_name:快取檔名稱。

  • backend:設定快取的儲存機制,預設使用sqlite進行儲存。
    支援四種不同的儲存機制,分別為memory、sqlite、mongoDB、redis。在設定儲存機制為mongoDB、redis時需要提前安裝對應的模組。pip install pymongo; pip install redies。 
  • memory:以字典的形式將快取儲存在記憶體當中,程式執行完以後快取將被銷燬 
  • sqlite:將快取儲存在sqlite資料庫中 
  • mongoDB:將快取儲存在mongoDB資料庫中 
  • redis:將快取儲存在redis中 
  • expire_after:設定快取的有效時間,預設永久有效。 
  • allowable_codes:設定狀態碼。 
  • allowable_methods:設定請求方式,預設get,表示只有get請求才可以生成快取。 
  • session_factory:設定快取執行的物件,需要實現CachedSession類。 
  • **backend_options:如果快取的儲存方式為sqlit、mongo、redis資料庫,該參數列示設定資料庫的連線方式。

自定義設定快取的例子1:設定快取檔案型別

設定快取檔案型別的程式碼如下:

#設定快取:任選其一
requests_cache.install_cache('demo_cache')#demo_cache.sqlite 做快取
#demo_cache資料夾做快取,刪除及表示清空快取
requests_cache.install_cache('demo_cache', backend='filesystem')
#快取資料夾便會使用系統的臨時目錄,而不會在程式碼區建立快取資料夾。
requests_cache.install_cache('demo_cache', backend='filesystem', use_temp=True)
#快取資料夾便會使用系統的專用快取資料夾,而不會在程式碼區建立快取資料夾
requests_cache.install_cache('demo_cache', backend='filesystem', use_cache_dir=True)
#Redis  ,需要安裝redis-py  pip install redies
backend = requests_cache.RedisCache(host='localhost', port=6379)
requests_cache.install_cache('demo_cache', backend=backend)

其他不同格式:

MongoDB 安裝pymongo pip install pymongo;

呼叫requests_cache.MongoCache 儲存為’mongodb’

gridfs 安裝pymongo

呼叫requests_cache.GridFSCache 儲存為’gridfs’

DynamoDB boto3 呼叫requests_cache.DynamoDbCache 儲存為’dynamodb’ 

Memory 以字典的形式將快取儲存在記憶體當中,程式執行完以後快取將被銷燬 呼叫requests_cache.BaseCache 儲存為’memory’

自定義設定快取的例子2:設定快取儲存內容

具體例子程式碼如下:

import time
import requests
import requests_cache
#只快取post
requests_cache.install_cache('demo_cache2', allowable_methods=['POST'])
#只快取200返回值的請求
requests_cache.install_cache('demo_cache2', allowable_codes=(200,))

只快取200返回值的請求

設定快取的過期時間:

#site1.com 的內容就會快取 30 秒,site2.com/static 的內容就永遠不會過期
urls_expire_after = {'*.site1.com': 30, 'site2.com/static': -1}
requests_cache.install_cache(
    'demo_cache2', urls_expire_after=urls_expire_after)

在響應頭中,瀏覽器會根據cache_control引數來確定是否儲存快取,在設定requests_cache快取時,可以對cache_control引數設定,使其儲存瀏覽器不需要儲存的內容。

# 儲存頭中,cache_control設為不儲存的請求
requests_cache.install_cache('demo_cache3', cache_control=True)
start = time.time()
session = requests.Session()
for i in range(10):
    session.get('http://httpbin.org/delay/1')
    print(f'Finished {i + 1} requests')
end = time.time()
print('Cost time for get', end - start)
start = time.time()
for i in range(10):
    session.post('http://httpbin.org/delay/1')
    print(f'Finished {i + 1} requests')
end = time.time()
print('Cost time for post', end - start)

在 Request Headers 裡面加上了 Cache-Control 為 no-store,這樣的話,即使我們宣告了快取那也不會生效

session.get('http://httpbin.org/delay/1',               
    headers={                   
    'Cache-Control': 'no-store'               
    }
)

以上就是python反反爬蟲技術限制連續請求時間處理的詳細內容,更多關於python反反爬蟲連續請求限制的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com