返回介绍

13.4 请求与响应

发布于 2024-01-26 22:39:51 字数 5643 浏览 0 评论 0 收藏 0

在编写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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文