13.4 请求与响应
在编写Spider模块中接触最紧密的是请求和响应。上一章我们讲解了如何简单地构造Request对象和解析Response对象,下面对这两个对象进行详细分析。
13.4.1 Request对象
一个Request对象代表着一个HTTP请求,通常在Spider类中产生,然后传递给下载器,最后返回一个响应。
类原型:class scrapy.http.Request(url[,callback,method=’GET‘,headers,body,cookies,meta,encoding=’utf-8‘,priority=0,dont_filter=False,errback])
构造参数说明:
·url(string):请求的链接。
·callback(callable):指定用于解析请求响应的方法。如果没有指定,默认使用spider的parse()方法。
·method(string):HTTP请求方式,默认为GET。
·meta(dict):可以用来初始化Request.meta属性。
·body(str or unicode):请求的body。
·headers(dict):请求头。如果传入的为None,请求头不会被发送。
·cookies(dict or list):请求的cookie信息。
·encoding(string):请求的编码,默认为UTF-8。
·priority(int):请求的优先级,默认为0。优先级被调度器用来安排处理请求的顺序。
·dont_filter(boolean):表明该请求不应由调度器过滤。适用场景为你想多次执行相同请求的时候。小心使用它,否则你会进入爬行循环。默认为False。
·errback(callable):如果在处理请求的过程中出现异常,指定的方法将会被调用。
下面介绍一下cookies参数的设置,有两种方式:
·使用字典发送:
request_with_cookies = Request(url="http://www.example.com", cookies={'currency': 'USD', 'coun try': 'UY'})
·使用字典列表发送:
request_with_cookies = Request(url="http://www.example.com", cookies=[{'name': 'currency', 'value': 'USD', 'domain': 'example.com', 'path': '/currency'}])
后面的这种方式可以定制Cookie中的domain和path属性。如果想把cookie信息保存到之后的请求中,这种方式会很有用。
当一些网站返回cookie信息,它们会被保存到cookie域中,在之后的请求时发送出去,这是一个典型的浏览器行为。但是由于某些原因,如果不想和现有的cookie进行合并,可以设置Request.meta中dont_merge_cookies字段的值。示例如下:
request_with_cookies = Request(url="http://www.example.com", cookies={'currency': 'USD', 'coun try': 'UY'}, meta={'dont_merge_cookies': True})
Request对象还提供一些属性和方法,如表13-1所示。
表13-1 常见属性与方法
除了我们能给meta设置任意的元数据,Scrapy还为Request.meta定义了一些特殊的键值,下面介绍其中一些常用的键值,如表13-2所示。
表13-2 常用键值
下面着重介绍一下FormRequest类,这是Request的子类,专门用来处理HTML表单,尤其对隐藏表单的处理非常方便,适合用来完成登录操作。
类原型:
class scrapy.http.FormRequest(url[, formdata, ...])
其中构造参数formdata可以是字典,也可以是可迭代的(key,value)元组,代表着需要提交的表单数据。示例如下:
return FormRequest(url="http://www.example.com/post/action", formdata={'name': 'John Doe', 'age': '27'}, callback=self.after_login)
通常网站通过<inputtype=“hidden”>实现对某些表单字段(如数据或是登录界面中的认证令牌等)的预填充,例如之前讲过的知乎网站的登录情况,如何处理这种隐藏表单呢?FormRequest类提供了一个类方法from_response。
方法原型如下:
from_response(response[, formname=None, formnumber=0, formdata=None, formxpath=None, clickdata=None, dont_click=False, ...])
常用参数说明:
·response:一个包含HTML表单的响应页面。
·formname(string):如果不为None,表单中的name属性将会被设定为这个值。
·formnumber(int):当响应页面中包含多个HTML表单时,本参数用来指定使用第几个表单,第一个表单数字为0。
·formdata(dict):本参数用来填充表单中属性的值。如果其中一个属性的值在响应页面中已经被预填充,但formdata中也指定了这个属性的值,将会把预填充的值覆盖掉。
·formxpath(string):如果页面中有多个HTML表单,可以用xpath表达式定位页面中的表单,第一个被匹配的将会被操作。
下面使用from_response方法来实现登录功能,示例如下:
import scrapy class LoginSpider(scrapy.Spider): name = 'example.com' start_urls = ['http://www.example.com/users/login.php'] def parse(self, response): return scrapy.FormRequest.from_response( response, formdata={'username': 'john', 'password': 'secret'}, callback=self.after_login ) def after_login(self, response): # check login succeed before going on if "authentication failed" in response.body: self.logger.error("Login failed") return
13.4.2 Response对象
Response对象代表着HTTP响应,Response通常是从下载器获取然后交给Spider处理。
类原型:
scrapy.http.Response(url[, status=200, headers, body, flags])
构造参数说明:
·url(string):响应的URL。
·headers(dict):响应头信息。
·status(integer):响应码,默认为200。
·body(str):响应的body。
·meta(dict):用来初始化Response.meta。
·flags(list):用来初始化Response.flags。
下面说一下常用的属性和方法,如表13-3所示。
表13-3 常用属性和方法
Response在Response的基础上添加了智能编码的功能。
类原型:
scrapy.http.TextResponse(url[, encoding[, ...]])
构造参数encoding是一个包含编码的字符串。如果使用一个unicode编码的body构造出TextResponse实例,那body属性会使用encoding进行编码。
TextResponse类除了具有Response的属性,还拥有自己的属性:
·encoding:包含编码的字符串。为什么说TextResponse具有智能编码的功能呢?编码的优先级由高到低如下所示:
1)首先选用构造器中传入的encoding。
2)选用HTTP头中Content-Type字段的编码。如果编码无效,则被忽略,继续尝试下面的规则。
3)选用响应body中的编码。
4)最后猜测响应的编码,这种方式是比较脆弱的。
·selector:以当前响应为目标的选择器实例。
TextResponse类除了支持Response中的方法,还支持以下方法:
·body_as_unicode():返回unicode编码的响应body内容。等价于:
response.body.decode(response.encoding)
·xpath(query):等价于TextResponse.selector.xpath(query)。示例如下:
response.xpath('// p')
·css(query):等价于TextResponse.selector.css(query)。示例如下:
response.css('p')
TextResponse还有两个子类HtmlResponse和XmlResponse,用法大同小异,不再赘述。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论