请求和响应
Scrapy 使用 Request
和 Response
对象来抓取网站。
通常,Request
对象在 spider 中生成,并在系统中传递,直到到达 Downloader(下载器)。Downloader 执行请求并返回一个 Response
对象,该对象再返回给发出请求的 spider。
Request
和 Response
类都有子类,这些子类添加了基类不需要的功能。这些内容将在下面的 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 (bytes 或 str) – 请求体。如果传入字符串,则会使用传入的
encoding
(默认为utf-8
)将其编码为字节。如果未提供body
,则存储一个空的字节对象。无论此参数的类型如何,最终存储的值都将是一个字节对象(绝不是字符串或None
)。headers (dict) –
此请求的请求头。字典值可以是字符串(用于单值请求头)或列表(用于多值请求头)。如果传递
None
作为值,则完全不会发送该 HTTP 请求头。注意
通过
Cookie
请求头设置的 Cookie 不会被 CookiesMiddleware 考虑。如果需要为请求设置 Cookie,请使用cookies
参数。这是一个目前已知并在处理中的限制。请求的 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 的
domain
和path
属性。这仅在 Cookie 保存用于后续请求时有用。当某个网站返回 Cookie(在响应中)时,这些 Cookie 将存储在该域的 Cookie 中,并在未来的请求中再次发送。这是任何常规 Web 浏览器的典型行为。
请注意,在
request.meta
中将dont_merge_cookies
键设置为True
会导致自定义 Cookie 被忽略。更多信息请参阅 CookiesMiddleware。
注意
通过
Cookie
请求头设置的 Cookie 不会被 CookiesMiddleware 考虑。如果需要为请求设置 Cookie,请使用scrapy.Request.cookies
参数。这是一个目前已知并在处理中的限制。encoding (str) – 此请求的编码(默认为
'utf-8'
)。此编码将用于对 URL 进行百分比编码,并将请求体转换为字节(如果作为字符串提供)。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
) 对象,包含请求头。
- callback: CallbackT | None
用于解析此请求收到后的
Response
的Callable
对象。可调用对象必须将响应作为其第一个参数,并支持通过
cb_kwargs
设置的任何额外关键字参数。除了任意可调用对象外,还支持以下值
None
(默认值),表示必须使用 spider 的parse()
方法。
如果在请求或响应处理期间发生未处理的异常,例如由 spider 中间件、下载器中间件 或下载处理程序 (
DOWNLOAD_HANDLERS
) 引发,则会改为调用errback
。提示
HttpErrorMiddleware
默认会针对非 2xx 响应引发异常,并将其发送到errback
。另请参阅
- errback: Callable[[Failure], Any] | None
用于处理请求或响应处理期间引发的异常的
Callable
对象。可调用对象必须将
Failure
作为其第一个参数。
- cb_kwargs
一个包含此请求的任意元数据的字典。其内容将作为关键字参数传递给 Request 的回调函数。对于新的 Request,它为空,这意味着默认情况下回调函数只接收一个
Response
对象作为参数。当使用
copy()
或replace()
方法克隆请求时,此字典会进行 浅拷贝,并且在 spider 中,也可以通过response.cb_kwargs
属性访问它。如果处理请求失败,可以在请求的 errback 中通过
failure.request.cb_kwargs
访问此字典。更多信息请参阅 在 errback 函数中访问额外数据。
- meta = {}
一个包含请求的任意元数据的字典。
您可以根据需要扩展请求元数据。
请求元数据也可以通过响应的
meta
属性访问。要在不同的 spider 回调函数之间传递数据,请考虑使用
cb_kwargs
。然而,在某些情况下,请求元数据可能是正确的选择,例如在所有后续请求中维护一些调试数据(例如源 URL)。请求元数据的一个常见用途是为 Scrapy 组件(扩展、中间件等)定义请求特定的参数。例如,如果您将
dont_retry
设置为True
,即使请求失败,RetryMiddleware
也不会重试该请求。请参阅 Request.meta 特殊键。您也可以在自定义的 Scrapy 组件中使用请求元数据,例如,保存与您的组件相关的请求状态信息。例如,
RetryMiddleware
使用retry_times
元数据键来跟踪请求目前已重试的次数。在 spider 回调函数中,将前一个请求的所有元数据复制到新的、后续请求中是一种不良实践,因为请求元数据可能包含由 Scrapy 组件设置的元数据,这些元数据不应该被复制到其他请求中。例如,将
retry_times
元数据键复制到后续请求中,可能会降低这些后续请求允许的重试次数。只有当新请求旨在替换旧请求时,才应该将一个请求的所有元数据复制到另一个请求中,这通常发生在从 下载器中间件 方法返回请求时。
- dont_filter: bool
此请求是否可以被支持过滤请求的 组件 过滤掉(
False
,默认),还是这些组件不应该过滤掉此请求(True
)。此属性通常设置为
True
,以防止重复请求被过滤掉。通过
start_urls
定义 spider 的起始 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 对象,其成员与原对象相同,但通过关键字参数指定新值的成员除外。
cb_kwargs
和meta
属性默认进行浅拷贝(除非作为参数提供了新值)。另请参阅 向回调函数传递额外数据。
- 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
子类(如JsonRequest
或XmlRpcRequest
)的from_curl()
,以及启用 下载器中间件 和 spider 中间件(例如DefaultHeadersMiddleware
,UserAgentMiddleware
或HttpCompressionMiddleware
),可能会修改Request
对象。要将 cURL 命令转换为 Scrapy 请求,您可以使用 curl2scrapy。
向回调函数传递额外数据
请求的回调是一个函数,当该请求的响应被下载后将被调用。回调函数将以下载的 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):
# 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,
)
注意
Request.cb_kwargs
在版本 1.7
中引入。在此之前,建议使用 Request.meta
来在回调之间传递信息。在 1.7
之后,Request.cb_kwargs
成为处理用户信息的首选方式,而 Request.meta
则保留用于与中间件 (middlewares) 和扩展 (extensions) 等组件通信。
使用错误回调 (errbacks) 捕获请求处理中的异常
请求的错误回调是一个函数,当在处理请求时发生异常时将被调用。
它接收一个 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 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
"https://example.invalid/", # DNS error expected
]
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))
# 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)
在错误回调函数中访问额外数据
如果请求处理失败,您可能需要访问回调函数的参数,以便在错误回调中根据这些参数进行进一步处理。以下示例展示了如何通过使用 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"],
)
请求指纹
在爬取的一些方面,例如过滤重复请求(参见 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.method
和request.body
的值。然后生成一个 SHA1 哈希。
编写自己的请求指纹生成器
请求指纹生成器是一个 组件,必须实现以下方法。
- fingerprint(self, request: scrapy.Request)
返回一个唯一标识 *request* 的
bytes
对象。另请参见 请求指纹限制。
默认请求指纹生成器 scrapy.utils.request.RequestFingerprinter
的 fingerprint()
方法使用了 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=222
,http://www.example.com/query?cat=222&id=111
。尽管这是两个不同的 URL,但它们都指向同一资源并且是等效的(即它们应该返回相同的响应)。
另一个例子是用于存储会话 ID 的 cookie。假设以下页面仅供认证用户访问:
http://www.example.com/members/offers.html
。许多网站使用 cookie 来存储会话 ID,这会给 HTTP 请求添加一个随机成分,因此在计算指纹时应该忽略它。
因此,在计算指纹时默认忽略请求头。如果要包含特定的请求头,请使用 include_headers 参数,它是一个要包含的 Request 请求头列表。
此外,服务器在处理请求时通常会忽略 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]
请求指纹限制
使用请求指纹的 Scrapy 组件可能会对您的 请求指纹生成器 生成的指纹格式施加额外的限制。
以下内置的 Scrapy 组件具有此类限制。
scrapy.extensions.httpcache.FilesystemCacheStorage
(HTTPCACHE_STORAGE
的默认值)请求指纹必须至少为 1 字节长。
HTTPCACHE_DIR
文件系统的路径和文件名长度限制也适用。在HTTPCACHE_DIR
内部,会创建以下目录结构:-
请求指纹的第一个字节(十六进制表示)
指纹(十六进制表示)
文件名(最长 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 特殊键
通过 Request.meta
属性可以包含任意数据,但有一些由 Scrapy 及其内置扩展识别的特殊键。
这些键包括:
ftp_password
(参见FTP_PASSWORD
了解更多信息)ftp_user
(参见FTP_USER
了解更多信息)
bindaddress
用于执行请求的出站 IP 地址。
download_timeout
下载器在超时前等待的时间(秒)。另请参见:DOWNLOAD_TIMEOUT
。
download_latency
从请求开始(即 HTTP 消息通过网络发送)到获取响应所花费的时间。这个 meta 键只在响应下载完成后可用。虽然大多数其他 meta 键用于控制 Scrapy 的行为,但这个键应被视为只读。
download_fail_on_dataloss
是否在响应损坏时失败。参见:DOWNLOAD_FAIL_ON_DATALOSS
。
max_retry_times
这个 meta 键用于设置每个请求的重试次数。初始化时,max_retry_times
meta 键的优先级高于 RETRY_TIMES
设置。
停止下载响应
从 bytes_received
或 headers_received
信号的处理程序中引发 StopDownload
异常将停止给定响应的下载。参见以下示例:
import scrapy
class StopSpider(scrapy.Spider):
name = "stop"
start_urls = ["https://docs.scrapy.net.cn/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' show that the full response was not downloaded
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)
默认情况下,结果响应由其相应的错误回调处理。要像本例一样调用其回调而不是错误回调,请将 fail=False
传递给 StopDownload
异常。
Request 子类
以下是内置的 Request
子类列表。您也可以继承它来实现您自己的自定义功能。
FormRequest 对象
FormRequest 类扩展了基本的 Request
类,提供了处理 HTML 表单的功能。它使用 lxml.html forms 根据 Response
对象中的表单数据预填充表单字段。
- class scrapy.FormRequest(url[, formdata, ...])
FormRequest
类为__init__()
方法添加了一个新的关键字参数。其余参数与Request
类相同,在此不再赘述。- 参数:
formdata (dict or collections.abc.Iterable) – 是一个字典(或 (键, 值) 元组的可迭代对象),包含 HTML 表单数据,这些数据将被进行 URL 编码并赋值给请求的 body。
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 中的一个错误,在选项值中包含前导或尾随空白的 select 元素上使用此方法将不起作用,该错误应在 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__()
方法。
请求使用示例
使用 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,
)
]
使用 FormRequest.from_response() 模拟用户登录
网站通常会通过 <input type="hidden">
元素提供预填充的表单字段,例如会话相关数据或身份验证令牌(用于登录页面)。在抓取时,您会希望这些字段被自动预填充,并且只覆盖其中几个,例如用户名和密码。您可以使用 FormRequest.from_response()
方法来完成此工作。以下是使用此方法的一个爬虫示例
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 类扩展了基本的 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
- 参数:
- 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 使用示例
发送带有 JSON 有效载荷的 JSON POST 请求
data = {
"name1": "value1",
"name2": "value2",
}
yield JsonRequest(url="http://www.example.com/post/action", data=data)
Response 对象
- class scrapy.http.Response(*args: Any, **kwargs: Any)[source]
表示 HTTP 响应的对象,通常由下载器(Downloader)下载并提供给爬虫(Spiders)进行处理。
- 参数:
url (str) – 此响应的 URL
status (int) – 响应的 HTTP 状态。默认为
200
。headers (dict) – 此响应的头部信息。字典值可以是字符串(对于单值头部)或列表(对于多值头部)。
body (bytes) – 响应正文。要以字符串形式访问解码后的文本,请使用具有编码感知能力的 Response 子类(例如
TextResponse
)中的response.text
。flags (list) – 一个列表,包含
Response.flags
属性的初始值。如果给定,该列表将被浅复制。request (scrapy.Request) –
Response.request
属性的初始值。这表示生成此响应的Request
。certificate (twisted.internet.ssl.Certificate) – 表示服务器 SSL 证书的对象。
ip_address (
ipaddress.IPv4Address
或ipaddress.IPv6Address
) – 响应来自的服务器的 IP 地址。protocol (
str
) – 用于下载响应的协议。例如:“HTTP/1.0”、“HTTP/1.1”、“h2”
2.0.0 版新增:
certificate
参数。2.1.0 版新增:
ip_address
参数。2.5.0 版新增:
protocol
参数。- status
表示响应 HTTP 状态的整数。示例:
200
、404
。
- headers
一个类似字典(
scrapy.http.headers.Headers
)的对象,包含响应头部信息。可以使用get()
访问值以返回具有指定名称的第一个头部值,或使用getlist()
返回具有指定名称的所有头部值。例如,此调用将返回头部中的所有 cookieresponse.headers.getlist('Set-Cookie')
- body
响应正文(以 bytes 为单位)。
如果您想要字符串形式的正文,请使用
TextResponse.text
(仅在TextResponse
及其子类中可用)。此属性是只读的。要更改 Response 的正文,请使用
replace()
。
- request
生成此响应的
Request
对象。此属性在 Scrapy 引擎中分配,在响应和请求通过所有 Downloader Middlewares 后。特别地,这意味着HTTP 重定向将从重定向之前的请求创建一个新请求。它拥有与原始请求大部分相同的元数据和属性,并被分配给重定向后的响应,而不是原始请求的传播。
Response.request.url
并不总是等于Response.url
此属性仅在爬虫代码和 Spider Middlewares 中可用,但在 Downloader Middlewares(尽管您可以通过其他方式在那里获得 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
。另请参阅
- flags
包含此响应标志的列表。标志是用于标记 Response 的标签。例如:
'cached'
、'redirected
’ 等。它们显示在 Response 的字符串表示中(__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()
使用。
- replace([url, status, headers, body, request, flags, cls])[source]
返回一个 Response 对象,其成员与原对象相同,但通过指定的关键字参数赋予新值的成员除外。
Response.meta
属性默认被复制。
- urljoin(url)[source]
通过将 Response 的
url
与可能的相对 url 组合来构造一个绝对 url。这是对
urljoin()
的包装,它仅仅是执行此调用的一个别名urllib.parse.urljoin(response.url, url)
- follow(url: str | Link, callback: CallbackT | None = None, method: str = 'GET', headers: Mapping[AnyStr, Any] | Iterable[tuple[AnyStr, Any]] | None = None, body: bytes | str | None = None, cookies: CookiesT | None = None, meta: dict[str, Any] | None = None, encoding: str | None = 'utf-8', priority: int = 0, dont_filter: bool = False, errback: Callable[[Failure], Any] | None = None, cb_kwargs: dict[str, Any] | None = None, flags: list[str] | None = None) Request [source]
返回一个
Request
实例,用于跟踪一个链接url
。它接受与Request.__init__()
方法相同的参数,但url
可以是相对 URL 或Link
对象,而不仅仅是绝对 URL。TextResponse
提供了follow()
方法,除了支持绝对/相对 URL 和 Link 对象外,还支持选择器。2.0 版本加入: 参数 flags。
- follow_all(urls: Iterable[str | Link], callback: CallbackT | None = None, method: str = 'GET', headers: Mapping[AnyStr, Any] | Iterable[tuple[AnyStr, Any]] | None = None, body: bytes | str | None = None, cookies: CookiesT | None = None, meta: dict[str, Any] | None = None, encoding: str | None = 'utf-8', priority: int = 0, dont_filter: bool = False, errback: Callable[[Failure], Any] | None = None, cb_kwargs: dict[str, Any] | None = None, flags: list[str] | None = None) Iterable[Request] [source]
2.0 版新增。
返回一个
Request
实例的可迭代对象,用于跟踪urls
中的所有链接。它接受与Request.__init__()
方法相同的参数,但urls
的元素可以是相对 URL 或Link
对象,而不仅仅是绝对 URL。TextResponse
提供了follow_all()
方法,除了支持绝对/相对 URL 和 Link 对象外,还支持选择器。
Response 子类
以下是可用的内置 Response 子类列表。您也可以子类化 Response 类来实现您自己的功能。
TextResponse 对象
- class scrapy.http.TextResponse(url[, encoding[, ...]])[source]
TextResponse
对象在基础Response
类(该类仅用于二进制数据,如图像、声音或任何媒体文件)的基础上增加了编码能力。TextResponse
对象除了基础Response
对象外,还支持一个新的__init__()
方法参数。其余功能与Response
类相同,此处不再赘述。- 参数:
encoding (str) – 一个字符串,包含用于此响应的编码。如果您使用字符串作为正文创建一个
TextResponse
对象,它将被转换为使用此编码编码的字节。如果 encoding 是None
(默认),编码将改为在响应头和正文中查找。
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
类对此不提供任何特殊功能。但是,HtmlResponse
和XmlResponse
类提供了。通过查看响应体推断出的编码。这是更脆弱的方法,但也是最后尝试的方法。
- 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.[*]')
- follow(url: str | Link | parsel.Selector, callback: CallbackT | None = None, method: str = 'GET', headers: Mapping[AnyStr, Any] | Iterable[tuple[AnyStr, Any]] | None = None, body: bytes | str | None = None, cookies: CookiesT | None = None, meta: dict[str, Any] | None = None, encoding: str | None = None, priority: int = 0, dont_filter: bool = False, errback: Callable[[Failure], Any] | None = None, cb_kwargs: dict[str, Any] | None = None, flags: list[str] | None = None) Request [source]
返回一个
Request
实例,用于跟踪一个链接url
。它接受与Request.__init__()
方法相同的参数,但url
不仅可以是绝对 URL,还可以是相对 URL
一个
Link
对象,例如 Link Extractors 的结果一个
Selector
对象,用于<link>
或<a>
元素,例如response.css('a.my_link')[0]
一个属性
Selector
(不是 SelectorList),例如response.css('a::attr(href)')[0]
或response.xpath('//img/@src')[0]
参阅 创建请求的快捷方式 以获取用法示例。
- follow_all(urls: Iterable[str | Link] | parsel.SelectorList | None = None, callback: CallbackT | None = None, method: str = 'GET', headers: Mapping[AnyStr, Any] | Iterable[tuple[AnyStr, Any]] | None = None, body: bytes | str | None = None, cookies: CookiesT | None = None, meta: dict[str, Any] | None = None, encoding: str | None = None, priority: int = 0, dont_filter: bool = False, errback: Callable[[Failure], Any] | None = None, cb_kwargs: dict[str, Any] | None = None, flags: list[str] | None = None, css: str | None = None, xpath: str | None = None) Iterable[Request] [source]
一个生成器,用于生成
Request
实例以追踪urls
中的所有链接。它接受与Request
的__init__()
方法相同的参数,但每个urls
元素不需要是绝对 URL,可以是以下任一类型相对 URL
一个
Link
对象,例如 Link Extractors 的结果一个
Selector
对象,用于<link>
或<a>
元素,例如response.css('a.my_link')[0]
一个属性
Selector
(不是 SelectorList),例如response.css('a::attr(href)')[0]
或response.xpath('//img/@src')[0]
此外,接受
css
和xpath
参数可在follow_all()
方法内部执行链接提取(仅接受urls
、css
和xpath
中的一个参数)。注意,当将
SelectorList
作为urls
参数的实参传递,或使用css
或xpath
参数时,此方法不会为无法获取链接的选择器生成请求(例如,没有href
属性的锚标签)。
- urljoin(url)[source]
通过将 Response 的基本 URL 与可能的相对 URL 组合来构建绝对 URL。基本 URL 应从
<base>
标签中提取,如果没有此类标签,则使用Response.url
。
HtmlResponse 对象
- class scrapy.http.HtmlResponse(url[, ...])[source]
HtmlResponse
类是TextResponse
的子类,通过查看 HTML meta http-equiv 属性来添加编码自动发现支持。参阅TextResponse.encoding
。
XmlResponse 对象
- class scrapy.http.XmlResponse(url[, ...])[source]
XmlResponse
类是TextResponse
的子类,通过查看 XML 声明行来添加编码自动发现支持。参阅TextResponse.encoding
。
JsonResponse 对象
- class scrapy.http.JsonResponse(url[, ...])[source]
JsonResponse
类是TextResponse
的子类,当响应在其 Content-Type 头部中具有 JSON MIME 类型时使用。