今天在爬另外一家网站数据时,想直接从 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
。