今天在爬另外一家網站數據時,想直接從 ajax 接口入手,可是發現這些 request 加了額外參數來防止爬取,即在 request header 裏,有一對隨機的 key-value
參數:形如 e931588bc0dfbc5e6323 : c43dfe7cdc49b6318f43907ad4e7d9b69a23719d2e3b7b59799124408aa11cf383f459a4a558af8c64b289b7d974982aad58db705ac6784460733bd21784bde0
,故意讓你猜不到。python
可是操做了一會,我總結了以下規律:ajax
一、每一個不一樣的接口 url,對應不一樣的 key ,但這個 key 刷新頁面是不會變得。(看來 key 跟 url 有關)算法
二、每一個 key 對應的 value 一直在變。(過後才知道 value 是根據 url 和 post body 共同決定的)json
因而經過網站被混淆過的 js ,耐心的打斷點分析。api
過程略。安全
最後發現:post
key 和 value 都是經過 HMAC(Keyed-Hashing for Message Authentication)
算法得來的。網站
HMAC 其實就等於咱們日常用的 MD5 / SHA-1 去加 salt 的操做。而採用 HMAC 的好處就是,替代咱們本身的 salt 算法,使得程序算法更標準化,也更安全。編碼
HMAC 可選擇搭配 MD5 / SHA-1 或等等。這裏用的是 SHA512
。url
>>> import hmac >>> key = b'secret' >>> message = b'Hello, world!' >>> h = hmac.new(key, message, digestmod='MD5') >>> h.hexdigest() 'fa4ee7d173f2d97ee79022d1a7355bcf'
注意:傳入的 key 和 message 都是bytes
類型,因此str
類型須要首先被編碼爲bytes
。
注意:敏感信息被隱藏處理。
import hashlib import hmac import requests import json host = 'http://example.com' # request's param - 變化值 uri = '/api/search/example' data = { "cityName": "上海", "cityCode": "31", # 等等 } # hmac's secret - 固定值 secret = b'abcdefg' # calculate key sign_key = hmac.new(secret, uri.lower().encode(), hashlib.sha512).hexdigest() header_key = sign_key[10:30] # calculate value sign_value = (uri.lower()+uri.lower() + json.dumps(data, separators=(',', ':'), ensure_ascii=False)).lower() header_value = hmac.new(secret, sign_value.encode(), hashlib.sha512).hexdigest() # print result print(header_key, header_value)
而後咱們把算出來的 key 和 value 塞入到每一次請求的 header 裏,便可成功調用。
上面代碼在算 value 的時候,用了 json.dumps()
,把中文 上海
轉爲了 "\u4e0a\u6d77"
,而不是上海
,致使接口一直報錯。
解決辦法:json.dumps 多傳一個參數 ensure_ascii=False
。