Lzh on GitHub

Scrapy 使用 RequestResponse 对象来抓取网站。

通常,Request 对象在爬虫中生成,并传递到整个系统,直到它们到达下载器,下载器执行请求并返回一个 Response 对象,该对象返回到发出请求的爬虫。

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

Request 对象

class scrapy.Request(*args: Any, **kwargs: Any)[source]

表示一个 HTTP 请求,通常在 Spider 中生成并由 Downloader 执行,从而生成一个 Response

参数:

  • url (str) – 此请求的 URL。 如果 URL 无效,则会引发 ValueError 异常。
  • callback (Callable[Concatenate[Response, ...], Any] | None) – 设置 callback,默认为 None。 2.0 版更改:当指定 errback 参数时,不再需要 callback 参数。
  • method (str) – 此请求的 HTTP 方法。默认为 'GET'
  • meta (dict) – Request.meta 属性的初始值。如果给出,则在此参数中传递的字典将被浅复制。
  • body (bytesstr) – 请求正文。如果传递字符串,则使用传递的 encoding(默认为 utf-8)将其编码为字节。如果未给出 body,则存储一个空字节对象。无论此参数的类型如何,存储的最终值都将是字节对象(绝不是字符串或 None)。
  • headers (dict) – 此请求的标头。字典值可以是字符串(用于单值标头)或列表(用于多值标头)。如果传递 None 作为值,则根本不会发送 HTTP 标头。 警告 通过 Cookie 标头设置的 Cookie 不被 CookiesMiddleware 考虑。如果您需要为请求设置 Cookie,请使用 cookies 参数。这是一个已知的当前限制,正在努力解决。
  • cookies (dictlist) – 请求 Cookie。这些可以以两种形式发送。 使用字典:
    request_with_cookies = Request(
        url="http://www.example.com",
        cookies={"currency": "USD", "country": "UY"},
    )
    
    使用字典列表:
    request_with_cookies = Request(
        url="https://www.example.com",
        cookies=[
            {
                "name": "currency",
                "value": "USD",
                "domain": "example.com",
                "path": "/currency",
                "secure": True,
            },
        ],
    )
    
    后一种形式允许自定义 Cookie 的 domainpath 属性。这仅在 Cookie 保存以供后续请求时有用。 当某些站点返回 Cookie(在响应中)时,这些 Cookie 会存储在该域的 Cookie 中,并将在未来的请求中再次发送。这是任何常规 Web 浏览器的典型行为。 请注意,在 request.meta 中将 dont_merge_cookies 键设置为 True 会导致自定义 Cookie 被忽略。 有关更多信息,请参阅 CookiesMiddleware警告 通过 Cookie 标头设置的 Cookie 不被 CookiesMiddleware 考虑。如果您需要为请求设置 Cookie,请使用 scrapy.Request.cookies 参数。这是一个已知的当前限制,正在努力解决。 从 2.6.0 版开始新增:值为 boolfloatint 的 Cookie 将转换为 str
  • encoding (str) – 此请求的编码(默认为 'utf-8')。此编码将用于对 URL 进行百分比编码,并将正文转换为字节(如果作为字符串给出)。
  • priority (int) – 设置 priority,默认为 0
  • dont_filter (bool) – 设置 dont_filter,默认为 False
  • errback (Callable[[Failure], Any] | None) – 设置 errback,默认为 None。 2.0 版更改:当指定 errback 参数时,不再需要 callback 参数。
  • flags (list) – 发送到请求的标志,可用于日志记录或类似目的。
  • cb_kwargs (dict) – 一个字典,包含任意数据,将作为关键字参数传递给 Request 的回调函数。

url

一个字符串,包含此请求的 URL。请记住,此属性包含转义的 URL,因此它可能与 __init__() 方法中传递的 URL 不同。 此属性是只读的。要更改 Request 的 URL,请使用 replace()

method

一个字符串,表示请求中的 HTTP 方法。保证为大写。示例:"GET""POST""PUT" 等。

headers

一个字典式 (scrapy.http.headers.Headers) 对象,其中包含请求标头。

body

请求正文为字节。 此属性是只读的。要更改 Request 的正文,请使用 replace()

callback: CallbackT | None

Callable,用于在收到此请求的 Response 后对其进行解析。 可调用对象必须将响应作为其第一个参数,并支持通过 cb_kwargs 设置的任何附加关键字参数。 除了任意可调用对象,还支持以下值:

  • None(默认),表示必须使用爬虫的 parse() 方法。
  • NO_CALLBACK()

如果在请求或响应处理期间引发未处理的异常,即由爬虫中间件下载器中间件或下载处理程序 (DOWNLOAD_HANDLERS) 引发,则会调用 errback

提示

HttpErrorMiddleware 默认情况下会为非 2xx 响应引发异常,将其发送到 errback

另请参阅

将额外数据传递给回调函数

errback: Callable[[Failure], Any] | None

Callable,用于处理请求或响应处理期间引发的异常。 可调用对象必须将 Failure 作为其第一个参数。

另请参阅

使用 errback 捕获请求处理中的异常

priority: int

默认值:0调度器可用于请求优先级的值。 内置调度器优先处理优先级值更高的请求。 允许负值。

cb_kwargs

一个字典,其中包含此请求的任意元数据。其内容将作为关键字参数传递给 Request 的回调函数。对于新的 Request,它为空,这意味着默认情况下回调函数只接收一个 Response 对象作为参数。

当使用 copy()replace() 方法克隆请求时,此字典会浅复制,并且在您的爬虫中也可以通过 response.cb_kwargs 属性访问。

如果处理请求失败,则可以在请求的 errback 中将此字典作为 failure.request.cb_kwargs 访问。有关更多信息,请参阅在 errback 函数中访问额外数据

meta = {}

一个用于请求的任意元数据字典。 您可以根据需要扩展请求元数据。 请求元数据也可以通过响应的 meta 属性访问。 要将数据从一个爬虫回调传递到另一个回调,请考虑使用 cb_kwargs。但是,在某些情况下,请求元数据可能是正确的选择,例如在所有后续请求中维护一些调试数据(例如源 URL)。 请求元数据的一个常见用途是为 Scrapy 组件(扩展、中间件等)定义请求特定参数。例如,如果将 dont_retry 设置为 True,则 RetryMiddleware 将永远不会重试该请求,即使它失败。请参阅Request.meta 特殊键。 您还可以在自定义 Scrapy 组件中使用请求元数据,例如,维护与您的组件相关的请求状态信息。例如,RetryMiddleware 使用 retry_times 元数据键来跟踪请求到目前为止已重试的次数。 在爬虫回调中将前一个请求的所有元数据复制到新的后续请求中是一种不好的做法,因为请求元数据可能包含 Scrapy 组件设置的元数据,而这些元数据不打算复制到其他请求中。例如,将 retry_times 元数据键复制到后续请求中可能会降低这些后续请求允许的重试次数。 只有当新请求旨在替换旧请求时,才应将所有请求元数据从一个请求复制到另一个请求,就像从下载器中间件方法返回请求时通常情况一样。 另请注意,copy()replace() 请求方法会浅复制请求元数据。

dont_filter: bool

此请求是否可能被支持过滤请求的组件过滤掉(False,默认),或者这些组件不应该过滤掉此请求(True)。 此属性通常设置为 True 以防止重复请求被过滤掉。 通过 start_urls 定义爬虫的起始 URL 时,此属性默认启用。请参阅 start()

attributes: tuple[str, ...] = ('url', 'callback', 'method', 'headers', 'body', 'cookies', 'meta', 'encoding', 'priority', 'dont_filter', 'errback', 'flags', 'cb_kwargs')

一个 str 对象元组,包含类的所有公共属性的名称,这些属性也是 __init__() 方法的关键字参数。 目前由 Request.replace()Request.to_dict()request_from_dict() 使用。

copy()[source]

返回一个作为此 Request 副本的新 Request。另请参阅:将额外数据传递给回调函数

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

返回一个 Request 对象,其成员与此 Request 相同,但通过指定的任何关键字参数赋予新值的成员除外。cb_kwargsmeta 属性默认浅复制(除非给出新值作为参数)。另请参阅将额外数据传递给回调函数

classmethod from_curl(curl_command: str, ignore_unknown_options: bool = True, **kwargs: Any) -> Self[source]

从包含 cURL 命令的字符串创建 Request 对象。它填充 HTTP 方法、URL、标头、Cookie 和正文。它接受与 Request 类相同的参数,优先并覆盖 cURL 命令中包含的相同参数的值。

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

警告

使用 Request 子类(例如 JsonRequestXmlRpcRequest)的 from_curl(),以及启用下载器中间件爬虫中间件(例如 DefaultHeadersMiddlewareUserAgentMiddlewareHttpCompressionMiddleware)可能会修改 Request 对象。

要将 cURL 命令转换为 Scrapy 请求,您可以使用 curl2scrapy

to_dict(*, spider: Spider | None = None) -> dict[str, Any][source]

返回包含 Request 数据的字典。 使用 request_from_dict() 转换回 Request 对象。 如果给出爬虫,此方法将尝试找出用作回调和 errback 的爬虫方法的名称并将其包含在输出字典中,如果找不到则会引发异常。

scrapy.http.request.NO_CALLBACK(*args: Any, **kwargs: Any) -> NoReturn[source]

当分配给 Requestcallback 参数时,它表示请求根本不打算有爬虫回调。 例如:

Request("https://example.com", callback=NO_CALLBACK)

此值应由创建和处理自己请求的组件使用,例如通过 scrapy.core.engine.ExecutionEngine.download(),以便处理此类请求的下载器中间件可以将其与旨在用于 parse() 回调的请求区别对待。

scrapy.utils.request.request_from_dict(d: dict[str, Any], *, spider: Spider | None = None) -> Request[source]

从字典创建 Request 对象。 如果给定爬虫,它将尝试通过查看爬虫中具有相同名称的方法来解析回调。

Passing additional data to callback functions (将额外数据传递给回调函数)

请求的回调函数是在下载该请求的响应时将调用的函数。回调函数将以下载的 Response 对象作为其第一个参数进行调用。

示例:

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

def parse_page2(self, response):
    # 这将记录 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"  # 为回调添加更多参数
    yield request

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

警告

Request.cb_kwargs 在 1.7 版中引入。在此之前,建议使用 Request.meta 在回调之间传递信息。1.7 版之后,Request.cb_kwargs 成为处理用户信息的首选方式,而 Request.meta 则留给与中间件和扩展等组件的通信。

Using errbacks to catch exceptions in request processing (使用 errback 捕获请求处理中的异常)

请求的 errback 是一个函数,当在处理请求时引发异常时,它将被调用。

它接收一个 Failure 作为第一个参数,可用于跟踪连接建立超时、DNS 错误等。

以下是一个示例爬虫,它记录所有错误并在需要时捕获一些特定错误:

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
        "http://www.httpbin.org/status/404",  # 未找到错误
        "http://www.httpbin.org/status/500",  # 服务器问题
        "http://www.httpbin.org:12345/",  # 无响应主机,期望超时
        "https://example.invalid/",  # 期望 DNS 错误
    ]

    async def start(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 爬虫中间件
            # 您可以获取非 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)

Accessing additional data in errback functions (在 errback 函数中访问额外数据)

如果处理请求失败,您可能希望访问回调函数的参数,以便在 errback 中根据参数进行进一步处理。以下示例展示了如何通过使用 Failure.request.cb_kwargs 来实现此目的:

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 fingerprints (请求指纹)

在某些抓取方面,例如过滤重复请求(请参阅 DUPEFILTER_CLASS)或缓存响应(请参阅 HTTPCACHE_POLICY),您需要能够从 Request 对象生成一个简短、唯一的标识符:请求指纹。

您通常不需要担心请求指纹,默认的请求指纹生成器适用于大多数项目。

但是,没有通用的方法可以从请求生成唯一的标识符,因为不同的情况需要以不同的方式比较请求。例如,有时您可能需要不区分大小写地比较 URL、包含 URL 片段、排除某些 URL 查询参数、包含部分或全部标头等。

要更改如何为您的请求构建请求指纹,请使用 REQUEST_FINGERPRINTER_CLASS 设置。

REQUEST_FINGERPRINTER_CLASS

从 2.7 版开始新增。

默认值:scrapy.utils.request.RequestFingerprinter 一个请求指纹生成器类或其导入路径。

class scrapy.utils.request.RequestFingerprinter(crawler: Crawler | None = None)[source]

默认指纹生成器。 它考虑了 request.url 的规范版本 (w3lib.url.canonicalize_url()) 以及 request.methodrequest.body 的值。然后它生成一个 SHA1 散列。

Writing your own request fingerprinter (编写您自己的请求指纹生成器)

请求指纹生成器是一个组件,它必须实现以下方法:

fingerprint(self, request: scrapy.Request)

返回一个唯一标识 requestbytes 对象。 另请参阅请求指纹限制

默认请求指纹生成器 scrapy.utils.request.RequestFingerprinterfingerprint() 方法使用 scrapy.utils.request.fingerprint() 及其默认参数。对于一些常见用例,您也可以在 fingerprint() 方法实现中使用 scrapy.utils.request.fingerprint()

scrapy.utils.request.fingerprint(request: Request, *, include_headers: Iterable[bytes | str] | None = None, keep_fragments: bool = False) -> bytes[source]

返回请求指纹。 请求指纹是一个唯一标识请求指向的资源的散列。例如,考虑以下两个 URL:http://www.example.com/query?id=111&cat=222http://www.example.com/query?cat=222&id=111。 尽管这些是两个不同的 URL,但它们都指向相同的资源并且是等效的(即它们应该返回相同的响应)。

另一个示例是用于存储会话 ID 的 Cookie。假设以下页面仅对经过身份验证的用户可访问:http://www.example.com/members/offers.html。 许多站点使用 Cookie 来存储会话 ID,这会向 HTTP 请求添加一个随机组件,因此在计算指纹时应将其忽略。 因此,在计算指纹时默认会忽略请求标头。如果您想包含特定标头,请使用 include_headers 参数,它是一个要包含的请求标头列表。

此外,服务器在处理请求时通常会忽略 URL 中的片段,因此在计算指纹时默认也会忽略它们。如果您想包含它们,请将 keep_fragments 参数设置为 True(例如,在使用无头浏览器处理请求时)。

例如,要考虑名为 X-ID 的请求标头的值:

# my_project/settings.py
REQUEST_FINGERPRINTER_CLASS = "my_project.utils.RequestFingerprinter"

# my_project/utils.py
from scrapy.utils.request import fingerprint

class RequestFingerprinter:
    def fingerprint(self, request):
        return fingerprint(request, include_headers=["X-ID"])

您也可以从头开始编写自己的指纹识别逻辑。

但是,如果您不使用 scrapy.utils.request.fingerprint(),请确保使用 WeakKeyDictionary 来缓存请求指纹:

  • 缓存通过确保指纹只为每个请求计算一次,而不是为需要请求指纹的每个 Scrapy 组件计算一次来节省 CPU。
  • 使用 WeakKeyDictionary 通过确保请求对象不会仅仅因为您在缓存字典中引用了它们而永远留在内存中来节省内存。

例如,仅考虑请求的 URL,不进行任何先前的 URL 规范化,也不考虑请求方法或正文:

from hashlib import sha1
from weakref import WeakKeyDictionary

from scrapy.utils.python import to_bytes


class RequestFingerprinter:
    cache = WeakKeyDictionary()

    def fingerprint(self, request):
        if request not in self.cache:
            fp = sha1()
            fp.update(to_bytes(request.url))
            self.cache[request] = fp.digest()
        return self.cache[request]

如果您需要能够从爬虫回调中覆盖任意请求的请求指纹,您可以实现一个请求指纹生成器,该生成器在可用时从 request.meta 读取指纹,然后回退到 scrapy.utils.request.fingerprint()。例如:

from scrapy.utils.request import fingerprint


class RequestFingerprinter:
    def fingerprint(self, request):
        if "fingerprint" in request.meta:
            return request.meta["fingerprint"]
        return fingerprint(request)

如果您需要重现与 Scrapy 2.6 相同的指纹识别算法,请使用以下请求指纹生成器:

from hashlib import sha1
from weakref import WeakKeyDictionary

from scrapy.utils.python import to_bytes
from w3lib.url import canonicalize_url


class RequestFingerprinter:
    cache = WeakKeyDictionary()

    def fingerprint(self, request):
        if request not in self.cache:
            fp = sha1()
            fp.update(to_bytes(request.method))
            fp.update(to_bytes(canonicalize_url(request.url)))
            fp.update(request.body or b"")
            self.cache[request] = fp.digest()
        return self.cache[request]

Request fingerprint restrictions (请求指纹限制)

使用请求指纹的 Scrapy 组件可能会对您的请求指纹生成器生成的指纹格式施加额外的限制。

以下内置 Scrapy 组件具有此类限制:

  • scrapy.extensions.httpcache.FilesystemCacheStorage (HTTPCACHE_STORAGE 的默认值) 请求指纹必须至少有 1 字节长。 HTTPCACHE_DIR 文件系统的路径和文件名长度限制也适用。在 HTTPCACHE_DIR 内部,创建以下目录结构:
    • Spider.name
    • 请求指纹的第一个字节(十六进制)
    • 指纹(十六进制)
    • 文件名最长 16 个字符 例如,如果请求指纹由 20 个字节(默认)组成,HTTPCACHE_DIR'/home/user/project/.scrapy/httpcache',并且您的爬虫名称为 'my_spider',则您的文件系统必须支持如下文件路径: /home/user/project/.scrapy/httpcache/my_spider/01/0123456789abcdef0123456789abcdef01234567/response_headers
  • scrapy.extensions.httpcache.DbmCacheStorage 底层 DBM 实现必须支持两倍于请求指纹字节数的键长度,加上 5。例如,如果请求指纹由 20 个字节(默认)组成,则必须支持 45 个字符长的键。

Request.meta special keys (Request.meta 特殊键)

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

它们是:

  • allow_offsite
  • autothrottle_dont_adjust_delay
  • bindaddress
  • cookiejar
  • dont_cache
  • dont_merge_cookies
  • dont_obey_robotstxt
  • dont_redirect
  • dont_retry
  • download_fail_on_dataloss
  • download_latency
  • download_maxsize
  • download_warnsize
  • download_timeout
  • ftp_password(有关更多信息,请参阅 FTP_PASSWORD
  • ftp_user(有关更多信息,请参阅 FTP_USER
  • handle_httpstatus_all
  • handle_httpstatus_list
  • is_start_request
  • max_retry_times
  • proxy
  • redirect_reasons
  • redirect_urls
  • referrer_policy

bindaddress

用于执行请求的出站 IP 地址。

download_timeout

下载器在超时前等待的时间(以秒为单位)。另请参阅:DOWNLOAD_TIMEOUT

download_latency

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

download_fail_on_dataloss

是否在损坏的响应上失败。请参阅:DOWNLOAD_FAIL_ON_DATALOSS

max_retry_times

此元键用于设置每个请求的重试次数。初始化时,max_retry_times 元键优先于 RETRY_TIMES 设置。

Stopping the download of a Response (停止响应的下载)

bytes_receivedheaders_received 信号的处理程序中引发 StopDownload 异常将停止给定响应的下载。请参阅以下示例:

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)

这会产生以下输出:

2020-05-19 17:26:12 [scrapy.core.engine] INFO: Spider opened
2020-05-19 17:26:12 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2020-05-19 17:26:13 [scrapy.core.downloader.handlers.http11] DEBUG: Download stopped for <GET https://docs.scrapy.org/en/latest/> from signal handler StopSpider.on_bytes_received
2020-05-19 17:26:13 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://docs.scrapy.org/en/latest/> (referer: None) ['download_stopped']
2020-05-19 17:26:13 [scrapy.core.scraper] DEBUG: Scraped from <200 https://docs.scrapy.org/en/latest/>
{'len': 279, 'last_chars': 'dth, initial-scale=1.0">\n  \n  <title>Scr'}
2020-05-19 17:26:13 [scrapy.core.engine] INFO: Closing spider (finished)

默认情况下,生成的响应由其相应的 errback 处理。要像此示例一样调用其回调,请将 fail=False 传递给 StopDownload 异常。

请求子类

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

FormRequest 对象

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

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

FormRequest 类为 __init__() 方法添加了一个新的关键字参数。其余参数与 Request 类相同,在此不赘述。

参数:

  • formdata (dictcollections.abc.Iterable) – 一个字典(或 (键, 值) 元组的可迭代对象),包含将进行 URL 编码并分配给请求正文的 HTML 表单数据。

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

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 参数。

警告

使用此方法处理选项值中包含前导或尾随空格的选择元素将无法正常工作,因为 lxml 中存在一个错误,该错误应在 lxml 3.8 及更高版本中修复。

参数:

  • response (Response 对象) – 包含 HTML 表单的响应,将用于预填充表单字段
  • formname (str) – 如果给定,将使用 name 属性设置为此值的表单。
  • formid (str) – 如果给定,将使用 id 属性设置为此值的表单。
  • formxpath (str) – 如果给定,将使用第一个匹配 xpath 的表单。
  • formcss (str) – 如果给定,将使用第一个匹配 css 选择器的表单。
  • formnumber (int) – 当响应包含多个表单时,要使用的表单编号。第一个(也是默认值)是 0
  • formdata (dict) – 要在表单数据中覆盖的字段。如果字段已存在于响应 <form> 元素中,则其值将被此参数中传递的值覆盖。如果此参数中传递的值为 None,则该字段将不会包含在请求中,即使它存在于响应 <form> 元素中。
  • clickdata (dict) – 用于查找被点击控件的属性。如果未给定,则将模拟点击第一个可点击元素提交表单数据。除了 html 属性,还可以通过 nr 属性(相对于表单内其他可提交输入的零基索引)来标识控件。
  • dont_click (bool) – 如果为 True,则表单数据将不点击任何元素而提交。

此类的其他参数直接传递给 FormRequest __init__() 方法。

Request usage examples (请求使用示例)

Using FormRequest to send data via HTTP POST (使用 FormRequest 通过 HTTP POST 发送数据)

如果您想在爬虫中模拟 HTML 表单 POST 并发送一些键值字段,您可以像这样返回一个 FormRequest 对象(来自您的爬虫):

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 (使用 FormRequest.from_response() 模拟用户登录)

网站通常通过 <input type="hidden"> 元素提供预填充的表单字段,例如与会话相关的数据或身份验证令牌(用于登录页面)。在抓取时,您会希望这些字段自动预填充,并且只覆盖其中几个,例如用户名和密码。您可以使用 FormRequest.from_response() 方法来完成此工作。这是一个使用它的示例爬虫:

import scrapy

def authentication_failed(response):
    # TODO: 检查响应内容,如果失败则返回 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

        # 继续使用已验证会话抓取...

JsonRequest

JsonRequest 类扩展了基本的 Request 类,增加了处理 JSON 请求的功能。

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

JsonRequest 类为 __init__() 方法添加了两个新的关键字参数。其余参数与 Request 类相同,此处不赘述。

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

参数:

  • data (object) – 任何需要 JSON 编码并分配给正文的 JSON 可序列化对象。如果提供了 body 参数,则此参数将被忽略。如果未提供 body 参数,但提供了 data 参数,则 method 将自动设置为 'POST'
  • dumps_kwargs (dict) – 将传递给用于将数据序列化为 JSON 格式的底层 json.dumps() 方法的参数。

attributes: tuple[str, ...] = ('url', 'callback', 'method', 'headers', 'body', 'cookies', 'meta', 'encoding', 'priority', 'dont_filter', 'errback', 'flags', 'cb_kwargs', 'dumps_kwargs')

一个 str 对象元组,包含类的所有公共属性的名称,这些属性也是 __init__() 方法的关键字参数。 目前由 Request.replace()Request.to_dict()request_from_dict() 使用。

JsonRequest usage example (JsonRequest 使用示例)

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

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

Response objects (Response 对象)

class scrapy.http.Response(*args: Any, **kwargs: Any)[source]

表示 HTTP 响应的对象,通常由下载器下载并提供给爬虫进行处理。

参数:

  • url (str) – 此响应的 URL
  • status (int) – 响应的 HTTP 状态。默认为 200
  • headers (dict) – 此响应的标头。字典值可以是字符串(用于单值标头)或列表(用于多值标头)。
  • body (bytes) – 响应正文。要将解码后的文本作为字符串访问,请从支持编码的响应子类(例如 TextResponse)中使用 response.text
  • flags (list) – 包含 Response.flags 属性初始值的列表。如果给定,该列表将进行浅复制。
  • request (scrapy.Request) – Response.request 属性的初始值。这表示生成此响应的 Request
  • certificate (twisted.internet.ssl.Certificate) – 表示服务器 SSL 证书的对象。
  • ip_address (ipaddress.IPv4Addressipaddress.IPv6Address) – 响应源自的服务器的 IP 地址。
  • protocol (str) – 用于下载响应的协议。例如:“HTTP/1.0”、“HTTP/1.1”、“h2” 从 2.0.0 版开始新增:certificate 参数。 从 2.1.0 版开始新增:ip_address 参数。 从 2.5.0 版开始新增:protocol 参数。

url

一个字符串,包含响应的 URL。 此属性是只读的。要更改 Response 的 URL,请使用 replace()

status

一个整数,表示响应的 HTTP 状态。示例:200404

headers

一个字典式 (scrapy.http.headers.Headers) 对象,其中包含响应标头。可以使用 get() 获取指定名称的第一个标头值,或使用 getlist() 获取指定名称的所有标头值。例如,此调用将为您提供标头中的所有 Cookie:

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

body

响应正文为字节。 如果您想要将正文作为字符串,请使用 TextResponse.text(仅在 TextResponse 及其子类中可用)。 此属性是只读的。要更改 Response 的正文,请使用 replace()

request

生成此响应的 Request 对象。此属性在 Scrapy 引擎中分配,在响应和请求都通过所有下载器中间件之后。具体来说,这意味着:

  • HTTP 重定向将从重定向前的请求创建一个新请求。它具有大部分相同的元数据和原始请求属性,并分配给重定向响应而不是原始请求的传播。
  • Response.request.url 不总是等于 Response.url

此属性仅在爬虫代码和爬虫中间件中可用,但在下载器中间件(尽管您可以通过其他方式在那里获得 Request)和 response_downloaded 信号的处理程序中不可用。

meta

Response.request 对象的 meta 属性的快捷方式(即 self.request.meta)。 与 Response.request 属性不同,Response.meta 属性在重定向和重试时传播,因此您将获得从爬虫发送的原始 Request.meta

另请参阅

Request.meta 属性

cb_kwargs

从 2.0 版开始新增。 Response.request 对象的 cb_kwargs 属性的快捷方式(即 self.request.cb_kwargs)。 与 Response.request 属性不同,Response.cb_kwargs 属性在重定向和重试时传播,因此您将获得从爬虫发送的原始 Request.cb_kwargs

另请参阅

Request.cb_kwargs 属性

flags

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

certificate

从 2.0.0 版开始新增。 一个 twisted.internet.ssl.Certificate 对象,表示服务器的 SSL 证书。 仅对 https 响应填充,否则为 None

ip_address

从 2.1.0 版开始新增。 响应源自的服务器的 IP 地址。 此属性目前仅由 HTTP 1.1 下载处理程序填充,即用于 http(s) 响应。对于其他处理程序,ip_address 始终为 None

protocol

从 2.5.0 版开始新增。 用于下载响应的协议。例如:“HTTP/1.0”、“HTTP/1.1” 此属性目前仅由 HTTP 下载处理程序填充,即用于 http(s) 响应。对于其他处理程序,protocol 始终为 None

attributes: tuple[str, ...] = ('url', 'status', 'headers', 'body', 'flags', 'request', 'certificate', 'ip_address', 'protocol')

一个 str 对象元组,包含类的所有公共属性的名称,这些属性也是 __init__() 方法的关键字参数。 目前由 Response.replace() 使用。

copy()[source]

返回一个作为此 Response 副本的新 Response。

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

返回一个 Response 对象,其成员与此 Response 相同,但通过指定的任何关键字参数赋予新值的成员除外。属性 Response.meta 默认复制。

urljoin(url)[source]

通过将 Response 的 url 与可能的相对 URL 组合来构造绝对 URL。 这是 urljoin() 的包装器,它只是以下调用的别名:

urllib.parse.urljoin(response.url, url)

返回一个 Request 实例以跟踪链接 url。它接受与 Request.__init__() 方法相同的参数,但 url 可以是相对 URL 或 Link 对象,而不仅仅是绝对 URL。 TextResponse 提供了一个 follow() 方法,除了绝对/相对 URL 和 Link 对象外,还支持选择器。 从 2.0 版开始新增:flags 参数。

从 2.0 版开始新增。 返回一个 Request 实例的可迭代对象,以跟踪 urls 中的所有链接。它接受与 Request.__init__() 方法相同的参数,但 urls 的元素可以是相对 URL 或 Link 对象,而不仅仅是绝对 URL。 TextResponse 提供了一个 follow_all() 方法,除了绝对/相对 URL 和 Link 对象外,还支持选择器。

Response subclasses (响应子类)

以下是可用的内置 Response 子类列表。您也可以对 Response 类进行子类化以实现自己的功能。

TextResponse 对象

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

TextResponse 对象为基本的 Response 类添加了编码功能,该类仅用于二进制数据,例如图像、声音或任何媒体文件。 TextResponse 对象支持一个新的 __init__() 方法参数,除了基本的 Response 对象。其余功能与 Response 类相同,此处不赘述。

参数:

  • encoding (str) – 一个字符串,包含用于此响应的编码。如果您使用字符串作为正文创建 TextResponse 对象,它将使用此编码转换为字节。如果 encodingNone(默认),则将在响应标头和正文中查找编码。

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

text

响应正文,作为字符串。 与 response.body.decode(response.encoding) 相同,但结果在第一次调用后会被缓存,因此您可以多次访问 response.text 而无需额外开销。

注意

str(response.body) 不是将响应正文转换为字符串的正确方法:

>>> str(b"body")
"b'body'"

encoding

此响应的编码字符串。编码按以下机制按顺序解析:

  • __init__() 方法 encoding 参数中传递的编码
  • Content-Type HTTP 标头中声明的编码。如果此编码无效(即未知),则将其忽略并尝试下一个解析机制。
  • 响应正文中声明的编码。TextResponse 类不提供任何特殊功能。但是,HtmlResponseXmlResponse 类提供此功能。
  • 通过查看响应正文推断出的编码。这是更脆弱的方法,但也是最后尝试的方法。

selector

一个以响应为目标的 Selector 实例。选择器在第一次访问时延迟实例化。

attributes: tuple[str, ...] = ('url', 'status', 'headers', 'body', 'flags', 'request', 'certificate', 'ip_address', 'protocol', 'encoding')

一个 str 对象元组,包含类的所有公共属性的名称,这些属性也是 __init__() 方法的关键字参数。 目前由 Response.replace() 使用。

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

jmespath(query)[source]

TextResponse.selector.jmespath(query) 的快捷方式:

response.jmespath('object.[*]')

xpath(query)[source]

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

response.xpath('//p')

css(query)[source]

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

response.css('p')

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

  • 相对 URL
  • Link 对象,例如 Link Extractors 的结果
  • <link><a> 元素的 Selector 对象,例如 response.css('a.my_link')[0]
  • 属性 Selector(不是 SelectorList),例如 response.css('a::attr(href)')[0]response.xpath('//img/@src')[0]

有关使用示例,请参阅创建请求的快捷方式

一个生成器,用于生成 Request 实例以跟踪 urls 中的所有链接。它接受与 Request__init__() 方法相同的参数,除了每个 urls 元素不需要是绝对 URL,它可以是以下任何一种:

  • 相对 URL
  • Link 对象,例如 Link Extractors 的结果
  • <link><a> 元素的 Selector 对象,例如 response.css('a.my_link')[0]
  • 属性 Selector(不是 SelectorList),例如 response.css('a::attr(href)')[0]response.xpath('//img/@src')[0]

此外,接受 cssxpath 参数以在 follow_all() 方法中执行链接提取(仅接受 urlscssxpath 中的一个)。

请注意,当将 SelectorList 作为 urls 参数的参数传递或使用 cssxpath 参数时,此方法不会为无法获取链接的选择器生成请求(例如,没有 href 属性的锚标签)。

json()[source]

从 2.2 版开始新增。 将 JSON 文档反序列化为 Python 对象。 从反序列化的 JSON 文档返回一个 Python 对象。结果在第一次调用后被缓存。

urljoin(url)[source]

通过将 Response 的基本 URL 与可能的相对 URL 组合来构造绝对 URL。基本 URL 将从 <base> 标签中提取,或者如果没有此类标签,则仅从 Response.url 中提取。

HtmlResponse objects (HtmlResponse 对象)

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

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

XmlResponse objects (XmlResponse 对象)

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

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

JsonResponse objects (JsonResponse 对象)

class scrapy.http.JsonResponse(url[, ...])[source]

JsonResponse 类是 TextResponse 的子类,当响应在其 Content-Type 标头中具有 JSON MIME 类型时使用。