欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Scrapy 框架翻译】请求和回应(Requests and Responses) 篇

程序员文章站 2022-05-08 16:46:51
...

版本号:Scrapy 2.4

内容介绍

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声明行编码自动发现支持。