我們知道,HTTP請求的 POST 方式,提交上去的數據有很多種格式。例如JSON/form-data/x-www-form-urlencoded等等。我們在 Postman 的 POST 請求里面,可以看到這些數據格式,如下圖所示:

雖然同樣都是 POST 方式,但是有些網站只能使用特定的格式才能正常返回數據。我們來看一個例子,現在向網址:http://exercise.kingname.info/ajax_1_postbackend POST 提交一個 JSON 字符串:{“name”:”xx”,”age”:24}可以正常得到返回:

但如果提交的數據格式不是 JSON,而是form-data,那么就會報錯,如下圖所示:

這也就是為什么在使用 requests 的時候,post 方法的第二個參數有data=和json=的區別,如下圖所示:

在使用 Scrapy 的時候,很多人都知道怎么提交 GET 請求,但卻不太清楚怎么提交 POST 請求。如果你在網上搜索,那么,你會看到有兩種回答:
第一種回答,會建議你使用scrapy.FormRequest。但這個方法提交的數據是form-data格式,如果網站需要接收 JSON 格式的數據,那么提交就會失敗。
第二種回答,會建議你使用scrapy.Request(url, method='POST', body=json.dumps(xxx))。這種方式確實可以成功提交 JSON 數據,但寫起來比較麻煩。
但如果你看過 Scrapy 的官方文檔Requests and Responses[1],你就會知道,實際上 Scrapy 原本就提供了一個專門用來POST 提交 JSON 數據的方式——JsonRequest。它的位置在scrapy.http.JsonRequest。並且使用起來跟 scrapy.Request一樣簡單:
import scrapy from scrapy.http import JsonRequest class ExampleSpider(scrapy.Spider): name = 'example' allowed_domains = ['xxx.com'] # start_urls = ['http://xxx.com/'] def start_requests(self): body = { 'name': 'kingname', 'age': 28 } url = 'http://exercise.kingname.info/ajax_1_postbackend' yield JsonRequest(url, data=body, callback=self.parse) def parse(self, response, *args, **kwargs): print(response.body.decode())
運行效果如下圖所示:

JsonRequest本來就是scrapy.Request的一個子類,所以所有能在scrapy.Request使用的參數,都可以直接在JsonRequest中使用。同時,它額外支持兩個參數,分別是data和dumps_kwargs。其中data參數的值就是一個可以被json.dumps序列化的對象,例如字典或者列表。而dumps_kwargs里面的參數,就是 json.dumps支持的那些參數,例如ensure_ascii=False、sort_keys=True等等。
大家遇到問題多看官方文檔,少在網上搜索些雜七雜八裝逼貨的爛博客。官方文檔是你最好的朋友。
參考資料
[1]
Requests and Responses: https://doc.scrapy.org/en/latest/topics/request-response.html#jsonrequest
未聞 Code技術交流群開放啦!群里既有國內一二線大廠在職員工,也有國內外高校在讀學生,既有十多年碼齡的編程老鳥,也有中小學剛剛入門的新人,學習氛圍良好!想入群的同學,請添加我的微信“mekingname”,備注“粉絲群”(謝絕廣告黨,非誠勿擾!)~

轉自:微信公眾號:未聞 Code
