成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

python爬蟲實現POST request payload形式的請求

瀏覽:4日期:2022-07-26 17:43:18

1. 背景

最近在爬取某個站點時,發現在POST數據時,使用的數據格式是request payload,有別于之前常見的 POST數據格式(Form data)。而使用Form data數據的提交方式時,無法提交成功。

python爬蟲實現POST request payload形式的請求

1.1. Http請求中Form Data 和 Request Payload的區別

AJAX Post請求中常用的兩種傳參數的形式:form data 和 request payload

1.1.1. Form data

get請求的時候,我們的參數直接反映在url里面,形式為key1=value1&key2=value2形式,比如:

http://news.baidu.com/ns?word=NBA&tn=news&from=news&cl=2&rn=20&ct=1

而如果是post請求,那么表單參數是在請求體中,也是以key1=value1&key2=value2的形式在請求體中。通過chrome的開發者工具可以看到,如下:

RequestURL:http://127.0.0.1:8080/test/test.doRequest Method:POSTStatus Code:200 OKRequest HeadersAccept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Encoding:gzip,deflate,sdchAccept-Language:zh-CN,zh;q=0.8,en;q=0.6AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2Cache-Control:max-age=0Connection:keep-aliveContent-Length:25Content-Type:application/x-www-form-urlencodedCookie:JSESSIONID=74AC93F9F572980B6FC10474CD8EDD8DHost:127.0.0.1:8080Origin:http://127.0.0.1:8080Referer:http://127.0.0.1:8080/test/index.jspUser-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36Form Dataname:mikanaddress:streetResponse HeadersContent-Length:2Date:Sun, 11 May 2014 11:05:33 GMTServer:Apache-Coyote/1.1

這里要注意post請求的Content-Type為application/x-www-form-urlencoded(默認的),參數是在請求體中,即上面請求中的Form Data。

前端代碼:提交數據

xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');

xhr.send('name=foo&value=bar');

后端代碼:接收提交的數據。在servlet中,可以通過request.getParameter(name)的形式來獲取表單參數。

/** * 獲取httpRequest的參數 * * @param request * @param name * @return */protected String getParameterValue(HttpServletRequest request, String name) { return StringUtils.trimToEmpty(request.getParameter(name));}

1.1.2. Request payload

如果使用原生AJAX POST請求的話,那么請求在chrome的開發者工具的表現如下,主要是參數在

Remote Address:192.168.234.240:80Request URL:http://tuanbeta3.XXX.com/qimage/upload.htmRequest Method:POSTStatus Code:200 OKRequest HeadersAccept:application/json, text/javascript, */*; q=0.01Accept-Encoding:gzip,deflate,sdchAccept-Language:zh-CN,zh;q=0.8,en;q=0.6Connection:keep-aliveContent-Length:151Content-Type:application/json;charset=UTF-8Cookie:JSESSIONID=E08388788943A651924CA0A10C7ACAD0Host:tuanbeta3.XXX.comOrigin:http://tuanbeta3.XXX.comReferer:http://tuanbeta3.XXX.com/qimage/customerlist.htm?menu=19User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36X-Requested-With:XMLHttpRequestRequest Payload[{widthEncode:NNNcaXN, heightEncode:NNNN5NN, displayUrl:201409/03/66I5P266rtT86oKq6,…}]Response HeadersConnection:keep-aliveContent-Encoding:gzipContent-Type:application/json;charset=UTF-8Date:Thu, 04 Sep 2014 06:49:44 GMTServer:nginx/1.4.7Transfer-Encoding:chunkedVary:Accept-Encoding

注意請求的Content-Type是application/json;charset=UTF-8,而請求表單的參數在Request Payload中。

后端代碼:獲取數據(這里使用org.apache.commons.io.):

/** * 從 request 獲取 payload 數據 * * @param request * @return * @throws IOException */private String getRequestPayload(HttpServletRequest request) throws IOException { return IOUtils.toString(request.getReader());}

1.1.3. 二者區別

如果一個請求的Content-Type設置為application/x-www-form-urlencoded,那么這個Post請求會被認為是Http Post表單請求,那么請求主體將以一個標準的鍵值對和&的querystring形式出現。這種方式是HTML表單的默認設置,所以在過去這種方式更加常見。

其他形式的POST請求,是放到 Request payload 中(現在是為了方便閱讀,使用了Json這樣的數據格式),請求的Content-Type設置為application/json;charset=UTF-8或者不指定。

2. 環境

python 3.6.1

系統:win7

IDE:pycharm

requests 2.14.2

scrapy 1.4.0

3. 使用requests模塊post payload請求

import jsonimport requestsimport datetimepostUrl = ’https://sellercentral.amazon.com/fba/profitabilitycalculator/getafnfee?profitcalcToken=en2kXFaY81m513NydhTZ9sdb6hoj3D’# payloadData數據payloadData = { ’afnPriceStr’: 10, ’currency’:’USD’, ’productInfoMapping’: { ’asin’: ’B072JW3Z6L’, ’dimensionUnit’: ’inches’, }}# 請求頭設置payloadHeader = { ’Host’: ’sellercentral.amazon.com’, ’Content-Type’: ’application/json’,}# 下載超時timeOut = 25# 代理proxy = '183.12.50.118:8080'proxies = { 'http': proxy, 'https': proxy,}r = requests.post(postUrl, data=json.dumps(payloadData), headers=payloadHeader)dumpJsonData = json.dumps(payloadData)print(f'dumpJsonData = {dumpJsonData}')res = requests.post(postUrl, data=dumpJsonData, headers=payloadHeader, timeout=timeOut, proxies=proxies, allow_redirects=True)# 下面這種直接填充json參數的方式也OK# res = requests.post(postUrl, json=payloadData, headers=header)print(f'responseTime = {datetime.datetime.now()}, statusCode = {res.status_code}, res text = {res.text}')

4. 在scrapy中post payload請求

這兒有個壞消息,那就是scrapy目前還不支持payload這種request請求。而且scrapy對formdata的請求也有很嚴格的要求,具體可以參考這篇文章:https://www.jb51.net/article/185824.htm

4.1. 分析scrapy源碼

參考注解

# 文件:E:MinicondaLibsite-packagesscrapyhttprequestform.pyclass FormRequest(Request): def __init__(self, *args, **kwargs): formdata = kwargs.pop(’formdata’, None) if formdata and kwargs.get(’method’) is None: kwargs[’method’] = ’POST’ super(FormRequest, self).__init__(*args, **kwargs) if formdata: items = formdata.items() if isinstance(formdata, dict) else formdata querystr = _urlencode(items, self.encoding) # 這兒寫死了,當提交數據時,設置好Content-Type,也就是form data類型 # 就算改寫這兒,后面也沒有對 json數據解析的處理 if self.method == ’POST’: self.headers.setdefault(b’Content-Type’, b’application/x-www-form-urlencoded’) self._set_body(querystr) else: self._set_url(self.url + (’&’ if ’?’ in self.url else ’?’) + querystr)

4.2. 思路:在scrapy中嵌入requests模塊

分析請求

返回的查詢結果

第一步:在爬蟲中構造請求,把所有的參數以及必要信息帶進去。

python爬蟲實現POST request payload形式的請求

python爬蟲實現POST request payload形式的請求

python爬蟲實現POST request payload形式的請求

返回的查詢結果

python爬蟲實現POST request payload形式的請求

第一步:在爬蟲中構造請求,把所有的參數以及必要信息帶進去。

# 文件 mySpider.py中payloadData = {}payloadData[’afnPriceStr’] = 0payloadData[’currency’] = asinInfo[’currencyCodeHidden’]payloadData[’futureFeeDate’] = asinInfo[’futureFeeDateHidden’]payloadData[’hasFutureFee’] = FalsepayloadData[’hasTaxPage’] = TruepayloadData[’marketPlaceId’] = asinInfo[’marketplaceIdHidden’]payloadData[’mfnPriceStr’] = 0payloadData[’mfnShippingPriceStr’] = 0payloadData[’productInfoMapping’] = {}payloadData[’productInfoMapping’][’asin’] = dataFieldJson[’asin’]payloadData[’productInfoMapping’][’binding’] = dataFieldJson[’binding’]payloadData[’productInfoMapping’][’dimensionUnit’] = dataFieldJson[’dimensionUnit’]payloadData[’productInfoMapping’][’dimensionUnitString’] = dataFieldJson[’dimensionUnitString’]payloadData[’productInfoMapping’][’encryptedMarketplaceId’] = dataFieldJson[’encryptedMarketplaceId’]payloadData[’productInfoMapping’][’gl’] = dataFieldJson[’gl’]payloadData[’productInfoMapping’][’height’] = dataFieldJson[’height’]payloadData[’productInfoMapping’][’imageUrl’] = dataFieldJson[’imageUrl’]payloadData[’productInfoMapping’][’isAsinLimits’] = dataFieldJson[’isAsinLimits’]payloadData[’productInfoMapping’][’isWhiteGloveRequired’] = dataFieldJson[’isWhiteGloveRequired’]payloadData[’productInfoMapping’][’length’] = dataFieldJson[’length’]payloadData[’productInfoMapping’][’link’] = dataFieldJson[’link’]payloadData[’productInfoMapping’][’originalUrl’] = dataFieldJson[’originalUrl’]payloadData[’productInfoMapping’][’productGroup’] = dataFieldJson[’productGroup’]payloadData[’productInfoMapping’][’subCategory’] = dataFieldJson[’subCategory’]payloadData[’productInfoMapping’][’thumbStringUrl’] = dataFieldJson[’thumbStringUrl’]payloadData[’productInfoMapping’][’title’] = dataFieldJson[’title’]payloadData[’productInfoMapping’][’weight’] = dataFieldJson[’weight’]payloadData[’productInfoMapping’][’weightUnit’] = dataFieldJson[’weightUnit’]payloadData[’productInfoMapping’][’weightUnitString’] = dataFieldJson[’weightUnitString’]payloadData[’productInfoMapping’][’width’] = dataFieldJson[’width’]# https://sellercentral.amazon.com/fba/profitabilitycalculator/getafnfee?profitcalcToken=en2kXFaY81m513NydhTZ9sdb6hoj3DpostUrl = f'https://sellercentral.amazon.com/fba/profitabilitycalculator/getafnfee?profitcalcToken={asinInfo[’tokenValue’]}'payloadHeader = { ’Host’: ’sellercentral.amazon.com’, ’Content-Type’: ’application/json’,}# scrapy源碼:self.headers.setdefault(b’Content-Type’, b’application/x-www-form-urlencoded’)print(f'payloadData = {payloadData}')# 這個request并不真正用來調度,去發出請求,因為這種方式構造方式,是無法提交成功的,會返回404錯誤# 這樣構造主要是把查詢參數提交出去,在下載中間件部分用request模塊下載,用 “payloadFlag” 標記這種requestyield Request(url = postUrl, headers = payloadHeader, meta = {’payloadFlag’: True, ’payloadData’: payloadData, ’headers’: payloadHeader, ’asinInfo’: asinInfo}, callback = self.parseAsinSearchFinallyRes, errback = self.error, dont_filter = True )

第二步:在中間件中,用requests模塊處理這個請求

# 文件:middlewares.pyclass PayLoadRequestMiddleware: def process_request(self, request, spider): # 如果有的請求是帶有payload請求的,在這個里面處理掉 if request.meta.get(’payloadFlag’, False): print(f'PayLoadRequestMiddleware enter') postUrl = request.url headers = request.meta.get(’headers’, {}) payloadData = request.meta.get(’payloadData’, {}) proxy = request.meta[’proxy’] proxies = { 'http': proxy, 'https': proxy, } timeOut = request.meta.get(’download_timeout’, 25) allow_redirects = request.meta.get(’dont_redirect’, False) dumpJsonData = json.dumps(payloadData) print(f'dumpJsonData = {dumpJsonData}') # 發現這個居然是個同步 阻塞的過程,太過影響速度了 res = requests.post(postUrl, data=dumpJsonData, headers=headers, timeout=timeOut, proxies=proxies, allow_redirects=allow_redirects) # res = requests.post(postUrl, json=payloadData, headers=header) print(f'responseTime = {datetime.datetime.now()}, res text = {res.text}, statusCode = {res.status_code}') if res.status_code > 199 and res.status_code < 300: # 返回Response,就進入callback函數處理,不會再去下載這個請求 return HtmlResponse(url=request.url, body=res.content, request=request, # 最好根據網頁的具體編碼而定 encoding=’utf-8’, status=200) else: print(f'request mode getting page error, Exception = {e}') return HtmlResponse(url=request.url, status=500, request=request)

4.3. 遺留下的問題

scrapy之所以強大,就是因為并發度高。大家都知道,由于Python GIL的原因,導致python無法通過多線程來提高性能。但是至少可以做到下載與解析同步的過程,在下載空檔的時候,進行數據的解析,調度等等,這都歸功于scrapy采用的異步結構。

但是,我們在中間件中使用requests模塊進行網頁下載,因為這是個同步過程,所以會阻塞在這個地方,拉低了整個爬蟲的效率。

所以,需要根據項目具體的情況,來決定合適的方案。當然這里又涉及到一個新的話題,就是scrapy提供的兩種爬取模式:深度優先模式和廣度優先模式。如何盡可能最大限度的利用scrapy的并發?在環境不穩定的情形下如何保證盡可能穩定的拿到數據?

深度優先模式和廣度優先模式是在settings中設置的。

# 文件: settings.py# DEPTH_PRIORITY(默認值為0)設置為一個正值后,Scrapy的調度器的隊列就會從LIFO變成FIFO,因此抓取規則就由DFO(深度優先)變成了BFO(廣度優先)DEPTH_PRIORITY = 1, # 廣度優先(肯呢個會累積大量的request,累計占有大量的內存,最終數據也在最后一批爬取)

深度優先:DEPTH_PRIORITY = 0

python爬蟲實現POST request payload形式的請求

廣度優先:DEPTH_PRIORITY = 1

python爬蟲實現POST request payload形式的請求

想將這個過程做成異步的,一直沒有思路,歡迎大神提出好的想法

以上這篇python爬蟲實現POST request payload形式的請求就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Python 編程
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
欧美日韩一区二区在线视频| 亚洲欧洲一区| 国产精一品亚洲二区在线视频| 国产精品欧美久久| 欧美激情艳妇裸体舞| 国产一区二区三区免费| 一本色道久久综合亚洲91 | 亚洲卡通动漫在线| 欧美体内she精视频在线观看| 日韩一卡二卡三卡国产欧美| 捆绑调教美女网站视频一区| 国产精品免费一区二区三区观看| 亚洲国产精品黑人久久久| 成人av电影在线观看| 欧美色综合网站| 天堂蜜桃一区二区三区| 午夜在线a亚洲v天堂网2018| 国产精品成人一区二区三区夜夜夜| 91网页版在线| 日韩一级大片在线| 激情图片小说一区| 欧美日韩国产欧美日美国产精品| 天天av天天翘天天综合网色鬼国产| 精品成人在线| 1区2区3区国产精品| 亚洲欧美影院| 国产精品天干天干在线综合| 91久色porny | 在线看国产一区| 亚洲h在线观看| 亚洲欧美日韩精品在线| 亚洲午夜免费视频| 国产精品久久久久久模特| 亚洲码国产岛国毛片在线| 亚洲免费大片| 亚洲免费观看高清完整版在线观看熊 | 欧美日韩一区二区三区在线| 日本成人在线不卡视频| 久久永久免费| 亚洲高清在线视频| 麻豆91精品| 日韩av成人高清| 欧美三级视频在线| 国产一区二区三区在线观看免费| 欧美日韩一区二区三区在线看 | 欧美少妇一区| 亚洲女女做受ⅹxx高潮| 一区二区三区av| 亚洲一区二区三区中文字幕在线| 久久久久高清| 蜜臀av性久久久久蜜臀aⅴ流畅 | 成人ar影院免费观看视频| 26uuu精品一区二区| 91免费看视频| 日韩美女久久久| 国产精品一区视频| 亚洲电影在线免费观看| 日本大香伊一区二区三区| 麻豆精品在线看| 3751色影院一区二区三区| 丁香婷婷综合五月| 国产视频一区在线观看| 在线不卡欧美| 一区二区三区欧美久久| 日本精品一区二区三区四区的功能| 蜜桃一区二区三区在线观看| 日韩欧美成人一区| 欧美精品一区二区视频| 亚洲人123区| 久久欧美肥婆一二区| 久久精品久久99精品久久| 日韩欧美国产高清| 欧美 日韩 国产精品免费观看| 最好看的中文字幕久久| 亚欧成人精品| 韩日精品视频一区| 国产蜜臀97一区二区三区| 亚洲高清二区| 视频一区二区三区中文字幕| 欧美日韩精品一区二区天天拍小说| 成人免费看片app下载| 国产人妖乱国产精品人妖| 日韩网站在线| 蜜臀a∨国产成人精品| 日韩一级黄色大片| 国产字幕视频一区二区| 亚洲国产人成综合网站| 5月丁香婷婷综合| 欧美激情aⅴ一区二区三区| 亚洲国产欧美日韩另类综合| 欧美挠脚心视频网站| aaa欧美日韩| 亚洲小说欧美激情另类| 色婷婷久久久久swag精品| 成人国产精品免费| 亚洲欧美国产毛片在线| 欧美日韩亚洲国产综合| 女人色偷偷aa久久天堂| 视频在线观看一区二区三区| 这里只有精品99re| 国产精品国码视频| 蜜桃久久久久久久| 国产亚洲一区二区三区| 久久综合激情| www.在线欧美| 亚洲第一狼人社区| 日韩精品中文字幕在线一区| 亚洲人体一区| 精品一区二区免费视频| 国产欧美精品一区二区色综合朱莉| 国产伦精品一区二区三区四区免费 | 日韩一区二区三| 午夜在线视频观看日韩17c| 国产精品小仙女| 亚洲精品一二三区| 6080午夜不卡| 国产伦精品一区二区三区照片91 | 欧美日韩在线一区二区| 在线观看欧美亚洲| 国产精品1区二区.| 一区二区在线观看不卡| 777色狠狠一区二区三区| 国内久久视频| 国产又粗又猛又爽又黄91精品| 中文一区一区三区高中清不卡| 久久久久综合| 91免费看`日韩一区二区| 麻豆成人91精品二区三区| 欧美极品少妇xxxxⅹ高跟鞋| 欧美日韩视频在线观看一区二区三区| 国产在线观看一区| 国产一区二区三区四区五区美女| 日韩理论片一区二区| 欧美不卡一区二区三区| 乱码第一页成人| 欧美日韩三级| 国产精品一二三四| 午夜私人影院久久久久| 国产欧美精品国产国产专区| 欧美午夜精品一区二区三区| 亚洲伦伦在线| 成人免费视频一区| 美女国产一区二区三区| 亚洲欧美日韩综合aⅴ视频| 久久亚洲精精品中文字幕早川悠里 | 亚洲成人免费电影| 国产网站一区二区| 欧美巨大另类极品videosbest | 337p粉嫩大胆色噜噜噜噜亚洲| 欧美性做爰猛烈叫床潮| 一区二区三区精品视频在线观看| 91网站在线观看视频| 国产一区二区在线观看视频| 日本91福利区| 《视频一区视频二区| 久久精品欧美一区二区三区麻豆| 欧美日韩中文另类| 国产精品综合| 国内视频一区| 99精品视频在线观看免费| 久久国产夜色精品鲁鲁99| 亚洲国产一区二区a毛片| 国产精品久久久久久妇女6080| 欧美精品一区男女天堂| 精品视频在线看| 91福利视频网站| 国产视频一区在线观看一区免费| 午夜国产精品视频| 丰满放荡岳乱妇91ww| 国产一区二区三区四区五区美女| 亚洲中国最大av网站| 中文字幕在线观看一区二区| 精品国产一区二区三区不卡 | 一本高清dvd不卡在线观看| 国内在线观看一区二区三区| 色综合婷婷久久| 粉嫩在线一区二区三区视频| 国产精品伊人色| 久久精品国产色蜜蜜麻豆| 日本亚洲视频在线| 亚洲香肠在线观看| 亚洲综合色丁香婷婷六月图片| 国产精品乱码一区二区三区软件| 久久久五月婷婷| 精品日韩一区二区三区免费视频| 欧美日韩激情在线| 色婷婷亚洲综合| 日本久久一区二区| 色综合久久精品| 日本韩国欧美国产| 91国产丝袜在线播放| 一本久久精品一区二区| 色88888久久久久久影院按摩| 一本久久综合亚洲鲁鲁五月天 | 欧美精品在线一区| 欧美日韩综合网| 女人天堂亚洲aⅴ在线观看| 欧美日本国产精品| 国产综合第一页| 国产欧美一区二区色老头|