【Scrapy 框架】「版本2.4.0源码」请求和回应(Requests and Responses) 详解篇

全部源码解析文章索引目录传送门

【Scrapy 框架】版本 2.4.0 源码篇:全部配置目录索引

内容介绍

Scrapy 中的 Request 和 Response 用于抓取网站的数据使用。

Request 对象在数据抓取中生成,并在系统中传递到达下载程序,后者执行请求并返回 Response 对象,该对象返回到发出请求的spider。

请求对象(Request objects)

class scrapy.http.Request(*args, **kwargs)

主要参数:
url (str) :请求的URL,如果URL无效,则ValueError引发异常

callback :回调函数,用于执行下一步的指定的回调方法

method:HTTP访问的方法,默认GET

meta:传递参数的字典

body :抓取的request文本信息,默认编码utf-8

headers : 设置的request的hearder信息,通常会采用新的方法随机更换

cookies:设置的request的cookies信息,一般存储方式为字典

encoding:默认为utf-8

priority:处理程序的优先级

dont_filter:是否忽略重复的过滤设置

errback:错误回调函数

flags:用于日志记录

cb_kwargs:任意数据的dict,这些数据将作为关键字参数传递给请求的回调函数

附加数据传递给回调函数

请求的回调是在下载该请求的响应时调用的函数

def parse_page1(self, response):
    return scrapy.Request("http://www.example.com/some_page.html",
                          callback=self.parse_page2)

def parse_page2(self, response):
    # this would log http://www.example.com/some_page.html
    self.logger.info("Visited %s", response.url)

在第二个回调中接收参数使用Request.cb_kwargs属性

def parse(self, response):
    request = scrapy.Request('http://www.example.com/index.html',
                             callback=self.parse_page2,
                             cb_kwargs=dict(main_url=response.url))
    request.cb_kwargs['foo'] = 'bar'  # add more arguments for the callback
    yield request

def parse_page2(self, response, main_url, foo):
    yield dict(
        main_url=main_url,
        other_url=response.url,
        foo=foo,
    )

请求处理中使用回退捕获异常

import scrapy

from scrapy.spidermiddlewares.httperror import HttpError
from twisted.internet.error import DNSLookupError
from twisted.internet.error import TimeoutError, TCPTimedOutError

class ErrbackSpider(scrapy.Spider):
    name = "errback_example"
    start_urls = [
        "http://www.httpbin.org/",              # 200 正常访问
        "http://www.httpbin.org/status/404",    # 404 无页面
        "http://www.httpbin.org/status/500",    # 500 服务器挂了
        "http://www.httpbin.org:12345/",        # 超时访问不到主机端口
        "http://www.httphttpbinbin.org/",       # DNS解析错误
    ]

    def start_requests(self):
        for u in self.start_urls:
            yield scrapy.Request(u, callback=self.parse_httpbin,
                                    errback=self.errback_httpbin,
                                    dont_filter=True)

    def parse_httpbin(self, response):
        self.logger.info('Got successful response from {}'.format(response.url))
		......

    def errback_httpbin(self, failure):
        # 全部的失败日志
        self.logger.error(repr(failure))
		# 如果想对某些错误进行特殊处理,需要失败的类型

        if failure.check(HttpError):
			# 这些异常来自HttpError Spider中间件获得非200的相应
            response = failure.value.response
            self.logger.error('HttpError on %s', response.url)

        elif failure.check(DNSLookupError):
            # 这是原始请求
            request = failure.request
            self.logger.error('DNSLookupError on %s', request.url)

        elif failure.check(TimeoutError, TCPTimedOutError):
            request = failure.request
            self.logger.error('TimeoutError on %s', request.url)

访问errback函数中的其他数据

在处理请求失败时,可能要访问回调函数的参数,可以根据errback中的参数进行处理。

def parse(self, response):
    request = scrapy.Request('http://www.example.com/index.html',
                             callback=self.parse_page2,
                             errback=self.errback_page2,
                             cb_kwargs=dict(main_url=response.url))
    yield request

def parse_page2(self, response, main_url):
    pass

def errback_page2(self, failure):
    yield dict(
        main_url=failure.request.cb_kwargs['main_url'],
    )

Request.meta 特别键

更多详细的操作参考中间件和实际应用案例,这里只做出一些简单的解释

  1. dont_redirect:如果Request.meta的dont_redirect密钥设置为True,则该中间件将忽略该请求。

  2. dont_retry:如果Request.meta的dont_retry密钥设置为True,则此中间件将忽略该请求。

  3. handle_httpstatus_list:如果仍要处理该范围以外的响应代码,则可以使用handle_httpstatus_list蜘蛛属性或HTTPERROR_ALLOWED_CODES设置指定spider能够处理的响应代码。

  4. handle_httpstatus_all:Request.meta的handle_httpstatus_list键也可以用于指定每个请求允许的响应代码。如果要允许请求的任何响应代码,也可以将元键handle_httpstatus_all设置为True。

  5. dont_merge_cookies:请求cookie。

  6. cookiejar:支持使用cookiejar请求元密钥在每个蜘蛛中保留多个cookie会话。默认情况下,它使用单个cookie罐(会话),但是您可以传递一个标识符以使用其他标识符。

  7. dont_cache:避免使用非True的dont_cache元键在每个策略上缓存响应。

  8. redirect_reasons:可以在redirect_reasons Request.meta键中找到redirect_urls中每个重定向的原因。

  9. redirect_urls:请求通过的URL(在重定向时)可以在redirect_urls Request.meta键中找到。

  10. bindaddress:用于执行请求的传出IP地址的IP。

  11. dont_obey_robotstxt:如果Request.meta的dont_obey_robotstxt密钥设置为True,则即使启用了ROBOTSTXT_OBEY,该中间件也将忽略该请求。

  12. download_timeout:超时之前,下载程序将等待的时间(以秒为单位)。另请参阅:DOWNLOAD_TIMEOUT。

  13. download_maxsize:可以使用download_maxsize spider属性为每个spider设置大小,并使用download_maxsize Request.meta键为每个请求设置大小。

  14. download_latency:自请求开始以来(即通过网络发送的HTTP消息),获取响应所花费的时间。仅在下载响应后,此元密钥才可用。虽然大多数其他元密钥用于控制Scrapy行为,但该密钥应该是只读的。

  15. download_fail_on_dataloss:是否因响应失败而失败。

  16. proxy:该中间件通过为Request对象设置代理元值来设置HTTP代理用于请求。

  17. ftp_user:当请求元中没有“ ftp_user”时,用于FTP连接的用户名。

  18. ftp_password:当请求元中没有“ ftp_password”时,用于FTP连接的密码。

  19. referrer_policy:填充请求“ Referer”标头时要应用的Referrer策略。

  20. max_retry_times:使用元密钥设置每个请求的重试时间。初始化后,max_retry_times元键的优先级高于RETRY_TIMES设置。

停止响应

import scrapy


class StopSpider(scrapy.Spider):
    name = "stop"
    start_urls = ["https://docs.scrapy.org/en/latest/"]

    @classmethod
    def from_crawler(cls, crawler):
        spider = super().from_crawler(crawler)
        crawler.signals.connect(spider.on_bytes_received, signal=scrapy.signals.bytes_received)
        return spider

    def parse(self, response):
        # “ last_chars”表明未下载完整响应
        yield {
    
    "len": len(response.text), "last_chars": response.text[-40:]}

    def on_bytes_received(self, data, request, spider):
        raise scrapy.exceptions.StopDownload(fail=False)

请求子类

class scrapy.http.FormRequest(url[, formdata, …])

FormRequest对象,用于传递参数的类,具有处理HTML表单的功能。返回一个新FormRequest对象,该对象的表单字段值预先填充了给定响应中包含的HTML元素中的表单字段值。

主要参数
response(Response对象):包含HTML表单的响应用于填充表单字段

formname(str):若定义,将使用name属性设置为该值的表单。

formid(str):若定义,将使用id属性设置为此值的表单。

formxpath(str):若定义,将使用与xpath匹配的第一个形式。

formcss(str):若定义,将使用与css选择器匹配的第一个形式。

formnumber(int):响应包含多个表单时要使用的表单数。第一个(也是默认值)是0。

formdata(dict):表单数据中要覆盖的字段。如果响应元素中已经存在一个字段,则该字段的值将被传入此参数的字段覆盖。如果在此参数中传递的值为None,则即使该字段存在于响应元素中,该字段也不会包含在请求中。

clickdata(dict):查找单击的控件的属性。如果未提供,则将模拟第一个clickable元素上的单击提交表单数据。除了html属性外,还可以通过该nr属性,通过相对于表单内其他可提交输入的,从零开始的索引来标识该控件。

dont_click(bool):如果为True,则无需单击任何元素即可提交表单数据。

使用FormRequest通过HTTP POST发送数据

import scrapy

def authentication_failed(response):
	# 检查响应的内容,如果失败,则返回True;如果成功,则返回False。
    pass

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):
        if authentication_failed(response):
            self.logger.error("Login failed")
            return

class scrapy.http.JsonRequest(url[, … data, dumps_kwargs])

JsonRequest 中 header设置

{
    
    
	'Content-Type':'application/json',
	'Accept':'application/json, text/javascript, */*; q=0.01'
}

参数说明:

  1. data(对象):是需要JSON编码并分配给主体的任何JSON可序列化对象。如果Request.body提供了参数,则将忽略此参数。如果Request.body未提供参数而提供了数据参数Request.method将’POST’自动设置为。
  2. dumps_kwargs(dict):将传递给基础json.dumps()方法的参数,该方法用于将数据序列化为JSON格式。

发送带有JSON有效负载的JSON POST请求

data = {
    
    
    'name1': 'value1',
    'name2': 'value2',
}
yield JsonRequest(url='http://www.example.com/post/action', data=data)

响应对象

class scrapy.http.Response(* args,** kwargs)

一个Response对象代表一个HTTP响应,通常会下载该HTTP响应(由下载程序下载),然后到Spider进行处理。

参数说明:

  1. url(str):该响应的URL

  2. status(int):响应的HTTP状态。默认为200。

  3. headers(dict):此响应的标头。dict值可以是字符串(对于单值标头)或列表(对于多值标头)。

  4. body (字节):响应正文。要以字符串形式访问解码后的文本,请使用 response.text可识别编码的 Response子类,例如TextResponse。

  5. flags (list):是一个包含Response.flags属性初始值的列表 。如果给出,列表将被浅表复制。

  6. request(scrapy.http.Request):Response.request属性的初始值。这表示Request生成此响应。

  7. certificate (twisted.internet.ssl.Certificate):代表服务器SSL证书的对象。

  8. ip_address(ipaddress.IPv4Address或ipaddress.IPv6Address):发起响应的服务器的IP地址。

响应子类

可用的内置Response子类的列表,可以对Response类进行子类化,以实现设置的功能。

class scrapy.http.TextResponse(url[, encoding[, …]])

TextResponse对象为基Response类增加了编码功能,该功能 只能用于二进制数据,例如图像,声音或任何媒体文件。

这里数据处理的方式同响应部分,都是对字符串进行处理,就不重复了。

class scrapy.http.HtmlResponse(url[, …])

HtmlResponse对象,其增加了通过查看HTML编码自动发现支持META HTTP-EQUIV属性。

class scrapy.http.XmlResponse(url[, …])

XmlResponse对象,其增加了通过查看XML声明行编码自动发现支持。

猜你喜欢

转载自blog.csdn.net/qq_20288327/article/details/113504317