Python 使用 Scrapy 发送 post 请求的坑
From:https://www.jb51.net/article/146769.htm
使用 requests 发送 post 请求
先来看看使用requests来发送post请求是多少好用,发送请求
Requests 简便的 API 意味着所有 HTTP 请求类型都是显而易见的。
例如,你可以这样发送一个 HTTP POST 请求:
>>>r = requests.post('http://httpbin.org/post', data = {'key':'value'})
使用data可以传递字典作为参数,同时也可以传递元祖
>>>payload = (('key1', 'value1'), ('key1', 'value2'))
>>>r = requests.post('http://httpbin.org/post', data=payload)
>>>print(r.text)
{..."form": {"key1": ["value1","value2"]},...
}
传递 json 是这样
>>>import json>>>url = 'https://api.github.com/some/endpoint'
>>>payload = {'some': 'data'}>>>r = requests.post(url, data=json.dumps(payload))
2.4.2 版的新加功能:
>>>url = 'https://api.github.com/some/endpoint'
>>>payload = {'some': 'data'}>>>r = requests.post(url, json=payload)
也就是说,你不需要对参数做什么变化,只需要关注使用data=还是json=,其余的requests都已经帮你做好了。
使用scrapy发送post请求
通过源码可知scrapy默认发送的get请求,当我们需要发送携带参数的请求或登录时,是需要post、请求的,以下面为例
from scrapy.spider import CrawlSpider
from scrapy.selector import Selector
import scrapy
import json
class LaGou(CrawlSpider):name = 'myspider'def start_requests(self):yield scrapy.FormRequest(url='https://www.******.com/jobs/positionAjax.json?city=%E5%B9%BF%E5%B7%9E&needAddtionalResult=false',formdata={'first': 'true',#这里不能给bool类型的True,requests模块中可以'pn': '1',#这里不能给int类型的1,requests模块中可以'kd': 'python'}, # 这里的formdata相当于requ模块中的data,key和value只能是键值对形式callback=self.parse)def parse(self, response):datas=json.loads(response.body.decode())['content']['positionResult']['result']for data in datas:print(data['companyFullName'] + str(data['positionId']))
官方推荐的 Using FormRequest to send data via HTTP POST
return [FormRequest(url="http://www.example.com/post/action",formdata={'name': 'John Doe', 'age': '27'},callback=self.after_post)]
这里使用的是FormRequest,并使用formdata传递参数,看到这里也是一个字典。
但是,超级坑的一点来了,今天折腾了一下午,使用这种方法发送请求,怎么发都会出问题,返回的数据一直都不是我想要的
return scrapy.FormRequest(url, formdata=(payload))
在网上找了很久,最终找到一种方法,使用scrapy.Request发送请求,就可以正常的获取数据。
return scrapy.Request(url, body=json.dumps(payload), method='POST', headers={'Content-Type': 'application/json'},)
参考:Send Post Request in Scrapy
my_data = {'field1': 'value1', 'field2': 'value2'}
request = scrapy.Request( url, method='POST', body=json.dumps(my_data), headers={'Content-Type':'application/json'} )
FormRequest 与 Request 区别
在文档中,几乎看不到差别,
The FormRequest class adds a new argument to the constructor. The remaining arguments are the same as for the Request class and are not documented here.
Parameters: formdata (dict or iterable of tuples) – is a dictionary (or iterable of (key, value) tuples) containing HTML Form data which will be url-encoded and assigned to the body of the request.
说FormRequest新增加了一个参数formdata,接受包含表单数据的字典或者可迭代的元组,并将其转化为请求的body。并且FormRequest是继承Request的
class 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 formdataquerystr = _urlencode(items, self.encoding)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)###def _urlencode(seq, enc):values = [(to_bytes(k, enc), to_bytes(v, enc))for k, vs in seqfor v in (vs if is_listlike(vs) else [vs])]return urlencode(values, doseq=1)
最终我们传递的{‘key': ‘value', ‘k': ‘v'}会被转化为'key=value&k=v' 并且默认的method是POST,再来看看Request
class Request(object_ref):def __init__(self, url, callback=None, method='GET', headers=None, body=None,cookies=None, meta=None, encoding='utf-8', priority=0,dont_filter=False, errback=None, flags=None):self._encoding = encoding # this one has to be set firstself.method = str(method).upper()
默认的方法是GET,其实并不影响。仍然可以发送post请求。这让我想起来requests中的request用法,这是定义请求的基础方法。
def request(method, url, **kwargs):"""Constructs and sends a :class:`Request <Request>`.:param method: method for the new :class:`Request` object.:param url: URL for the new :class:`Request` object.:param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.:param data: (optional) Dictionary or list of tuples ``[(key, value)]`` (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`.:param json: (optional) json data to send in the body of the :class:`Request`.:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.:param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a stringdefining the content type of the given file and ``custom_headers`` a dict-like object containing additional headersto add for the file.:param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.:param timeout: (optional) How many seconds to wait for the server to send databefore giving up, as a float, or a :ref:`(connect timeout, readtimeout) <timeouts>` tuple.:type timeout: float or tuple:param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.:type allow_redirects: bool:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.:param verify: (optional) Either a boolean, in which case it controls whether we verifythe server's TLS certificate, or a string, in which case it must be a pathto a CA bundle to use. Defaults to ``True``.:param stream: (optional) if ``False``, the response content will be immediately downloaded.:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.:return: :class:`Response <Response>` object:rtype: requests.ResponseUsage::>>> import requests>>> req = requests.request('GET', 'http://httpbin.org/get')<Response [200]>"""# By using the 'with' statement we are sure the session is closed, thus we# avoid leaving sockets open which can trigger a ResourceWarning in some# cases, and look like a memory leak in others.with sessions.Session() as session:return session.request(method=method, url=url, **kwargs)
Python 使用 Scrapy 发送 post 请求的坑相关推荐
- python使用scrapy_python使用scrapy发送post请求的坑
标签: 使用 requests 发送 post 请求 先来看看使用requests来发送post请求是多少好用,发送请求 Requests 简便的 API 意味着所有 HTTP 请求类型都是显而易见的 ...
- python requests是什么_如何基于Python + requests实现发送HTTP请求
这篇文章主要介绍了如何基于Python + requests实现发送HTTP请求,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.在接口自动化测试 ...
- python写页面发送post请求_Python模拟浏览器向CSDN发送post请求的方法,POST
目录 1.发送get请求的方法 import requests import json def GET(url): #get请求 req = requests.get(url) #输出状态码 prin ...
- 安装python爬虫scrapy踩过的那些坑和编程外的思考
'转载地址:http://www.cnblogs.com/rwxwsblog/p/4557123.html' 这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬 ...
- python使用urllib发送post请求_python使用urllib2提交http post请求的方法
Python模拟新浪微博登录 看到一篇Python模拟新浪微博登录的文章,想熟悉一下其中实现方式,并且顺便掌握python相关知识点. 代码 下面的代码是来自上面这篇文章,并稍作修改添加了一些注释. ...
- 使用 python requests 模块发送 http 请求及接收响应
内容概要 如何构建GET 与 POST request 请求消息 对 request 的header , query string, message body 定制化 http header参数 co ...
- python使用request发送post请求_python之使用request模块发送post和get请求
import requests import json #发送get请求并得到结果 # url = 'http://api.nnzhp.cn/api/user/stu_info?stu_name=小黑 ...
- Python 使用requests发送POST请求
一个http请求包括三个部分,为别为请求行,请求报头,消息主体,类似以下这样: 请求行 请求报头 消息主体 HTTP协议规定post提交的数据必须放在消息主体中,但是协议并没有规定必须使用什么编码 ...
- Python 使用requests发送POST请求总结
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/junli_chen/article/details/53670887 一个http请求包括三个部分, ...
最新文章
- ICRA 2021| SKD:基于显着性估计的点云关键点检测
- CentOS软/硬RAID安装方法
- 小强升职记梗概_《小强升职记》读后感
- 【转知乎】人工智能会是泡沫吗?
- websocket在web项目中的使用
- 【Android进阶学习】Http编程之HttpClient
- 【BZOJ2049】【codevs1839】洞穴探测,LCT练习
- 锁到底是一种怎样的存在?
- Android的手机震动
- python123用户登录的三次机会_用户登录三次机会(PYTHON)
- Python-模块导入-63
- Thingworx入门学习
- 英特尔vPro博锐技术激活
- Codeforces 645B Mischievous Mess Makers【逆序数】
- FFMpeg 4.1 音频检测
- 《淘宝网开店 拍摄 修图 设计 装修 实战150招》一一1.8 侧光拍摄增强轮廓感
- 如何判断两个链表是否相交并求出相交点
- Google AIY 套件将亮相香港!人工智能新一轮风潮袭来!
- 力扣算法题(11)动态规划
- Cesium中用到的图形技术——Computing the horizon occlusion point