Scrapy解決formrequest中formdata爲dict問題

在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&params=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})])

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章