Requests and Responses

Scrapy使用RequestResponse对象来爬网网站.

通常, Request对象是在Spider中生成的,并在整个系统中传递,直到它们到达Downloader,该Downloader执行请求并返回Response对象,该Response对象返回到发出请求的Spider中.

RequestResponse类都具有子类,这些子类添加了基类中不需要的功能. 这些在下面的Request子类Response子类中进行了描述.

Request objects

class scrapy.http.Request(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, cb_kwargs=None)

Request对象代表HTTP请求,通常在Spider中生成并由Downloader执行,从而生成Response .

Parameters:
  • url字符串 )–此请求的URL
  • callbackcallable )–将以请求的响应(一旦下载)作为第一个参数调用的函数. 有关更多信息,请参见下面的将其他数据传递给回调函数 . 如果请求未指定回调,则将使用Spider的parse()方法. 请注意,如果在处理过程中引发异常,则会调用errback.
  • method字符串 )–此请求的HTTP方法. 默认为'GET' .
  • metadict )– Request.meta属性的初始值. 如果给出,则在此参数中传递的字典将被浅表复制.
  • 正文str unicode )–请求正文. 如果传递了unicode ,则使用传递的encoding (默认为utf-8 )将其编码为str . 如果未指定body ,则将存储一个空字符串. 无论此参数的类型如何,存储的最终值将为str (从不unicodeNone ).
  • 标头dict )–此请求的标头. dict值可以是字符串(对于单值标头)或列表(对于多值标头). 如果将None作为值传递,则根本不会发送HTTP标头.
  • Cookies字典 列表 )–

    请求cookie. 这些可以两种形式发送.

    1. 使用字典:
       request_with_cookies = Request ( url = "http://www.example.com" ,
                                     cookies = { 'currency' : 'USD' , 'country' : 'UY' })
      
    2. 使用字典列表:
       request_with_cookies = Request ( url = "http://www.example.com" ,
                                     cookies = [{ 'name' : 'currency' ,
                                              'value' : 'USD' ,
                                              'domain' : 'example.com' ,
                                              'path' : '/currency' }])
      

    后一种形式允许自定义cookie的domainpath属性. 仅当cookie被保存用于以后的请求时,此功能才有用.

    当某些站点返回cookie(作为响应)时,它们将存储在该域的cookie中,并将在以后的请求中再次发送. 这是任何常规Web浏览器的典型行为.

    要创建不发送已存储的cookie且不存储已接收的cookie的请求,请在request.meta中将dont_merge_cookies键设置为True .

    发送手动定义的cookie并忽略cookie存储的请求示例:

     Request (
        url = "http://www.example.com" ,
        cookies = { 'currency' : 'USD' , 'country' : 'UY' },
        meta = { 'dont_merge_cookies' : True },
    )
    

    有关更多信息,请参见CookiesMiddleware .

  • encodingstring )–此请求的编码(默认为'utf-8' ). 此编码将用于对URL进行百分比编码,并将正文转换为str (如果以unicode给出).
  • priorityint )–此请求的优先级(默认为0 ). 调度程序使用优先级来定义用于处理请求的顺序. 具有较高优先级值的请求将更早执行. 允许使用负值以指示相对较低的优先级.
  • dont_filterboolean )–指示调度程序不应过滤此请求. 当您要多次执行相同的请求时,可使用此选项来忽略重复项过滤器. 谨慎使用它,否则您将进入爬网循环. 默认为False .
  • errbackcallable )–如果在处理请求时引发任何异常,将调用该函数. 这包括由于404 HTTP错误而失败的页面. 它接收一个Twisted Failure实例作为第一个参数. 有关更多信息,请参见下面的在处理请求时使用errbacks捕获异常 .
  • 标志列表 )–发送给请求的标志可用于记录或类似目的.
  • cb_kwargsdict )–带有任意数据的dict,它将作为关键字参数传递到请求的回调中.
url

包含此请求的URL的字符串. 请记住,此属性包含转义的URL,因此它可能不同于在构造函数中传递的URL.

该属性是只读的. 要更改请求的URL,请使用replace() .

method

表示请求中HTTP方法的字符串. 保证是大写的. 示例: "GET""POST""PUT"

headers

类似于字典的对象,其中包含请求标头.

body

包含请求主体的str.

该属性是只读的. 要更改Request的正文,请使用replace() .

meta

包含此请求的任意元数据的字典. 对于新请求,此字典为空,通常由不同的Scrapy组件(扩展,中间件等)填充. 因此,此dict中包含的数据取决于您启用的扩展.

有关Scrapy可以识别的特殊元密钥的列表,请参见Request.meta特殊密钥 .

当使用copy()replace()方法克隆请求时,此dict是浅复制的,也可以在您的Spider中从response.meta属性进行访问.

cb_kwargs

包含此请求的任意元数据的字典. 它的内容将作为关键字参数传递给请求的回调. 对于新请求,该字段为空,这意味着默认情况下,回调仅将Response对象作为参数.

当使用copy()replace()方法克隆请求时,此dict是浅复制的,也可以在您的Spider中从response.cb_kwargs属性进行访问.

copy()

返回一个新请求,该请求是该请求的副本. 另请参阅:将其他数据传递给回调函数 .

replace([url, method, headers, body, cookies, meta, flags, encoding, priority, dont_filter, callback, errback, cb_kwargs])

返回具有相同成员的Request对象,但那些通过指定关键字参数赋予新值的成员除外. 默认情况下, Request.cb_kwargsRequest.meta属性是浅复制的(除非将新值作为参数给出). 另请参见将其他数据传递给回调函数 .

classmethod from_curl(curl_command, ignore_unknown_options=True, **kwargs)

从包含cURL命令的字符串中创建一个Request对象. 它填充HTTP方法,URL,标题,cookie和正文. 它接受与Request类相同的参数,并具有优先级并覆盖cURL命令中包含的相同参数的值.

默认情况下,无法识别的选项将被忽略. 要在查找未知选项时引发错误,请通过传递ignore_unknown_options=False调用此方法.

Caution

使用来自Request子类(例如JSONRequestXmlRpcRequest from_curl() ,以及启用下载器中间件蜘蛛中间件 (例如DefaultHeadersMiddlewareUserAgentMiddlewareHttpCompressionMiddleware ,可以修改Request对象.

Passing additional data to callback functions

请求的回调是在下载请求的响应时将调用的函数. 将使用下载的Response对象作为其第一个参数调用回调函数.

Example:

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,
    )

Caution

1.7版中引入了Request.cb_kwargs . 在此之前,建议使用Request.meta在回调周围传递信息. 在1.7之后, Request.cb_kwargs成为处理用户信息的首选方式,而让Request.meta可以与中间件和扩展之类的组件进行通信.

Using errbacks to catch exceptions in request processing

请求的错误返回是在处理请求时引发异常时将调用的函数.

它接收到Twisted Failure实例作为第一个参数,可用于跟踪连接建立超时,DNS错误等.

Here’s an example spider logging all errors and catching some specific errors if needed:

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/",              # HTTP 200 expected
        "http://www.httpbin.org/status/404",    # Not found error
        "http://www.httpbin.org/status/500",    # server issue
        "http://www.httpbin.org:12345/",        # non-responding host, timeout expected
        "http://www.httphttpbinbin.org/",       # DNS error expected
    ]

    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))
        # do something useful here...

    def errback_httpbin(self, failure):
        # log all failures
        self.logger.error(repr(failure))

        # in case you want to do something special for some errors,
        # you may need the failure's type:

        if failure.check(HttpError):
            # these exceptions come from HttpError spider middleware
            # you can get the non-200 response
            response = failure.value.response
            self.logger.error('HttpError on %s', response.url)

        elif failure.check(DNSLookupError):
            # this is the original request
            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)

Request.meta special keys

Request.meta属性可以包含任何任意数据,但是Scrapy及其内置扩展可以识别一些特殊键.

那些是:

bindaddress

用于执行请求的传出IP地址的IP.

download_timeout

The amount of time (in secs) that the downloader will wait before timing out. See also: DOWNLOAD_TIMEOUT.

download_latency

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

download_fail_on_dataloss

是否因响应失败而失败. 请参阅: DOWNLOAD_FAIL_ON_DATALOSS .

max_retry_times

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

Request subclasses

这是内置的Request子类的列表. 您也可以将其子类化以实现自己的自定义功能.

FormRequest objects

FormRequest类使用处理HTML表单的功能扩展了基本Request . 它使用lxml.html表单使用来自Response对象的表单数据预填充表单字段.

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

FormRequest类向构造函数添加一个新的关键字参数. 其余参数与Request类的参数相同,在此未介绍.

Parameters:formdata (dict or 元组的迭代) – 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.

除了标准的Request方法外, FormRequest对象还支持以下类方法:

classmethod from_response(response[, formname=None, formid=None, formnumber=0, formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...])

返回一个新的FormRequest对象,该对象的表单字段值用给定响应中包含的HTML <form>元素中的值预先填充. 有关示例,请参见使用FormRequest.from_response()模拟用户登录 .

该策略是默认情况下自动模拟任何看起来可点击的表单控件的点击,例如<input type="submit"> . 即使这样做很方便,并且通常是所需的行为,但有时它可能会导致难以调试的问题. 例如,当处理使用javascript填充和/或提交的表单时,默认的from_response()行为可能不是最合适的. 要禁用此行为,可以将dont_click参数设置为True . 另外,如果要更改单击的控件(而不是禁用控件),还可以使用clickdata参数.

Caution

由于lxml中存在bug,因此对在选项值中具有前导或尾随空格的select元素使用此方法将不起作用,该错误应在lxml 3.8及更高版本中修复.

Parameters:
  • responseResponse对象)–包含HTML表单的响应,该表单将用于预填充表单字段
  • formnamestring )–如果给定,将使用name属性设置为此值的表单.
  • formidstring )–如果给定,将使用id属性设置为此值的表单.
  • formxpath字符串 )–如果给定,将使用与xpath匹配的第一个形式.
  • formcss字符串 )–如果给定,将使用与css选择器匹配的第一个形式.
  • formnumber整数 )–响应包含多个表单时要使用的表单数. 第一个(也是默认值)是0 .
  • formdatadict )–要在表单数据中覆盖的字段. 如果response <form>元素中已经存在一个字段,则该字段的值将被传入此参数的字段覆盖. 如果在此参数中传递的值为None ,则即使响应<form>元素中存在该字段,该字段也不会包含在请求中.
  • clickdatadict )–查找单击的控件的属性. 如果未提供,将在模拟第一个可点击元素的情况下提交表单数据. 除html属性外,还可以通过nr属性通过相对于表单中其他可提交输入的,从零开始的索引来标识控件.
  • dont_clickboolean )–如果为True,则无需单击任何元素即可提交表单数据.

此类方法的其他参数直接传递给FormRequest构造函数.

New in version 0.10.3: The formname parameter.

0.17版中的新功能: The formxpath parameter.

New in version 1.1.0: The formcss parameter.

1.1.0版的新功能: The formid parameter.

Request usage examples

Using FormRequest to send data via HTTP POST

如果要在Spider中模拟HTML Form POST并发送几个键值字段,则可以返回FormRequest对象(来自Spider),如下所示:

return [FormRequest(url="http://www.example.com/post/action",
                    formdata={'name': 'John Doe', 'age': '27'},
                    callback=self.after_post)]

Using FormRequest.from_response() to simulate a user login

It is usual for web sites to provide pre-populated form fields through <input type="hidden"> elements, such as session related data or authentication tokens (for login pages). When scraping, you’ll want these fields to be automatically pre-populated and only override a couple of them, such as the user name and password. You can use the FormRequest.from_response() method for this job. Here’s an example spider which uses it:

import scrapy

def authentication_failed(response):
    # TODO: Check the contents of the response and return True if it failed
    # or False if it succeeded.
    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

        # continue scraping with authenticated session...

JsonRequest

JsonRequest类使用处理JSON请求的功能扩展了基本Request类.

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

JsonRequest类向构造函数添加了两个新的关键字参数. 其余参数与Request类的参数相同,在此未介绍.

使用JsonRequest会将Content-Type标头设置为application/json ,将Accept标头设置为application/json, text/javascript, */*; q=0.01 application/json, text/javascript, */*; q=0.01

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

JsonRequest usage example

Sending a JSON POST request with a JSON payload:

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

Response objects

class scrapy.http.Response(url, status=200, headers=None, body=b'', flags=None, request=None)

Response对象代表HTTP响应,通常会下载该HTTP响应(由下载程序下载),然后将其馈送到Spider进行处理.

Parameters:
  • url字符串 )–该响应的URL
  • status整数 )–响应的HTTP状态. 默认为200 .
  • 标头dict )–此响应的标头. dict值可以是字符串(对于单值标头)或列表(对于多值标头).
  • 正文字节 )–响应正文. 要访问解码文本STR(在Python 2的Unicode),您可以使用response.text从编码感知响应子类 ,如TextResponse .
  • flagslist )–是一个包含Response.flags属性的初始值的列表. 如果给出,列表将被浅表复制.
  • requestRequest对象)– Response.request属性的初始值. 这表示生成此响应的Request .
url

包含响应的URL的字符串.

该属性是只读的. 要更改Response的URL,请使用replace() .

status

表示响应的HTTP状态的整数. 例如: 200404 .

headers

包含响应标头的类字典对象. 可以使用get()返回具有指定名称的第一个标头值或使用getlist()返回具有指定名称的所有标头值的值. 例如,此调用将为您提供标题中的所有cookie:

response.headers.getlist('Set-Cookie')
body

此响应的正文. 请记住,Response.body始终是一个字节对象. 如果要使用unicode版本,请使用TextResponse.text (仅在TextResponse和子类中可用).

该属性是只读的. 要更改Response的正文,请使用replace() .

request

生成此响应的Request对象. 在响应和请求通过所有Downloader Middlewares之后,将在Scrapy引擎中分配此属性. 特别是,这意味着:

  • HTTP重定向将导致原始请求(重定向前指向URL)被分配给重定向后的响应(重定向后带有最终URL).
  • Response.request.url并不总是等于Response.url
  • 该属性仅在Spider代码和Spider中间件中可用,而在Downloader中间件中(尽管您可以通过其他方式获得Request)和response_downloaded信号的处理程序中不可用.
meta

Response.request对象(即self.request.meta )的Request.meta属性的快捷方式.

不像Response.request属性,则Response.meta属性沿着重定向和重试传播,所以你会得到原始Request.meta从蜘蛛发送.

也可以看看

Request.meta attribute

flags

包含此响应标志的列表. 标志是用于标记响应的标签. 例如: 'cached''redirected "等.它们显示在响应的字符串表示形式( __str__方法)上,引擎用于记录日志.

copy()

返回一个新的响应,它是此响应的副本.

replace([url, status, headers, body, request, flags, cls])

返回具有相同成员的Response对象,但那些通过指定关键字参数赋予新值的成员除外. 默认情况下,将复制属性Response.meta .

urljoin(url)

通过将Response的url与可能的相对url组合来构造绝对url.

这是urlparse.urljoin的包装,它只是进行此调用的别名:

urlparse.urljoin(response.url, url)
follow(url, callback=None, method='GET', headers=None, body=None, cookies=None, meta=None, encoding='utf-8', priority=0, dont_filter=False, errback=None, cb_kwargs=None)

返回一个Request实例以跟随链接url . 它接受与Request.__init__方法相同的参数,但url可以是相对URL或scrapy.link.Link对象,而不仅仅是绝对URL.

TextResponse provides a follow() method which supports selectors in addition to absolute/relative URLs and Link objects.

Response subclasses

这是可用的内置Response子类的列表. 您还可以对Response类进行子类化,以实现自己的功能.

TextResponse objects

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

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

除基本Response对象外, TextResponse对象还支持新的构造函数参数. 其余功能与Response类的功能相同,在此未记录.

Parameters: encodingstring )–是一个字符串,其中包含用于此响应的编码. 如果使用unicode主体创建TextResponse对象,则将使用此编码对其进行编码(请记住body属性始终是字符串). 如果encodingNone (默认值),则将在响应标头和正文中查找编码.

除了标准Response属性外, TextResponse对象还支持以下属性:

text

响应主体,为unicode.

response.body.decode(response.encoding)相同,但是结果在第一次调用后被缓存,因此您可以多次访问response.text而不会产生额外开销.

Note

unicode(response.body)不是将响应正文转换为unicode的正确方法:您将使用系统默认编码(通常为ascii )而不是响应编码.

encoding

具有此响应编码的字符串. 通过依次尝试以下机制来解析编码:

  1. 构造函数encoding参数中传递的encoding
  2. Content-Type HTTP标头中声明的编码. 如果此编码无效(即未知),则将其忽略并尝试下一个解析机制.
  3. 在响应主体中声明的编码. TextResponse类对此不提供任何特殊功能. 但是, HtmlResponseXmlResponse类可以.
  4. 通过查看响应主体推断出的编码. 这是较脆弱的方法,但也是最后一个尝试过的方法.
selector

使用响应作为目标的Selector实例. 选择器在首次访问时被延迟实例化.

除标准Response方法外, TextResponse对象还支持以下方法:

xpath(query)

TextResponse.selector.xpath(query)快捷方式:

response.xpath('//p')
css(query)

TextResponse.selector.css(query)快捷方式:

response.css('p')
follow(url, callback=None, method='GET', headers=None, body=None, cookies=None, meta=None, encoding=None, priority=0, dont_filter=False, errback=None, cb_kwargs=None)

返回一个Request实例以跟随链接url . 它接受与Request.__init__方法相同的参数,但是url不仅可以是绝对URL,还可以是绝对URL.

  • 相对网址;
  • scrapy.link.Link对象(例如,链接提取器结果);
  • 属性选择器(不是SelectorList)-例如response.css('a::attr(href)')[0]response.xpath('//img/@src')[0] .
  • <a><link>元素的选择器,例如response.css('a.my_link')[0] .

See A shortcut for creating Requests for usage examples.

body_as_unicode()

text相同,但可以用作方法. 保留此方法是为了向后兼容. 请更喜欢response.text .

HtmlResponse objects

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

HtmlResponse类是HtmlResponse的子类, TextResponse通过查看HTML meta http-equiv属性来添加编码自动发现支持. 请参阅TextResponse.encoding .

XmlResponse objects

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

XmlResponse类的子类TextResponse它加入了通过查看XML声明行编码自动发现支持. 请参阅TextResponse.encoding .