在Scrapy的FormRequest中直接將formdata設置爲dict形式後,scrapy經過字節編碼形式的轉換,會發出一個非期望的request,例如:
FormRequest(url="**************************",
meta = {'cookiejar' : response.meta['cookiejar']},
formdata = {
'params': {"offset":10,"start":"10"},
'method': 'next',
})
我們此時將發送的表單數據,屬性params的值設置爲dict,原有的請求形式爲:
params=%7B%22offset%22%3A10%2C%22start%22%3A%2210%22%7D&method=next
經過錯誤的變換之後,發送的請求變爲:
params=start¶ms=offset&method=next
上面的url中%
開始的字符是經過bytes變換之後的形式,翻譯成我們能看懂的就是:
params={"offset":10,"start":"10"}&method=next
在Scrapy的源碼文件/http/request/form.py
中,定義了scrapy是如何將formdata處理:
items = formdata.items() if isinstance(formdata, dict) else formdata
def _urlencode(seq, enc):
values = [(to_bytes(k, enc), to_bytes(v, enc))
for k, vs in seq
for v in (vs if is_listlike(vs) else [vs])]
return urlencode(values, doseq=1)
其中seq就是原始的formdata.items(),enc的編碼格式,這裏我們忽略。經過items()方法執行後,原始的外圍的dict格式變成列表形式:
dict_items([('method', 'next'), ('params', {'start': '10', 'offset': 10})])
再經過_urlencode方法將items轉換成
[(b'method', b'next'), (b'params', b'start'), (b'params', b'offset')]
可以看到就是在調用_urlencode方法的時候出現了問題,上面的方法執行過後,會使字典形式的數據只保留了keys,將字典數據作爲的value的key分別當做字典數據value。
幸運的是,網絡中dict形式的請求是直接將{'':'','',''}
這種轉換成bytes形式傳遞,沒有再進行其他轉換,至於dic的解析則由服務器端處理,所以我們直接將dic的數據外面加上”,轉換成字符串形式。
formdata = {
'params': '{"offset":10,"start":"10"}',
'method': 'next',
}
此時變成了:
dict_items([('method', 'next'), ('params', {'start': '10', 'offset': 10})])