请求和响应¶
Scrapy 使用 Request
和 Response
对象来爬取网站。
通常,Request
对象在爬虫中生成,并通过系统传递,直到到达下载器,下载器执行请求并返回一个 Response
对象,该对象返回到发出请求的爬虫。
Request
和 Response
类都有子类,这些子类添加了基本类不需要的功能。这些将在下面的 请求子类 和 响应子类 中进行描述。
请求对象¶
- class scrapy.http.Request(*args: Any, **kwargs: Any)[source]¶
表示一个 HTTP 请求,通常在爬虫中生成并由下载器执行,从而生成一个
Response
。- 参数:
url (str) –
此请求的 URL
如果 URL 无效,则会引发
ValueError
异常。callback (collections.abc.Callable) –
将使用此请求的响应(一旦下载)作为其第一个参数调用的函数。
除了函数之外,还支持以下值
None
(默认值),表示必须使用爬虫的parse()
方法。
有关更多信息,请参阅 将额外数据传递给回调函数。
注意
如果在处理过程中引发异常,则会改为调用
errback
。method (str) – 此请求的 HTTP 方法。默认为
'GET'
。meta (dict) –
Request.meta
属性的初始值。如果给出,则此参数中传递的 dict 将被浅复制。body (bytes 或 str) – 请求主体。如果传递字符串,则使用传递的
encoding
(默认为utf-8
)将其编码为字节。如果未给出body
,则存储一个空的字节对象。无论此参数的类型如何,存储的最终值都将是一个字节对象(永远不是字符串或None
)。headers (dict) –
此请求的标头。dict 值可以是字符串(对于单值标头)或列表(对于多值标头)。如果传递
None
作为值,则根本不会发送 HTTP 标头。注意
通过
Cookie
标头设置的 Cookie 未被 CookiesMiddleware 考虑。如果您需要为请求设置 Cookie,请使用Request.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,请使用Request.cookies
参数。这是一个已知的当前限制,正在努力解决。encoding (str) – 请求的编码(默认为
'utf-8'
)。此编码将用于对 URL 进行百分比编码,以及将主体转换为字节(如果主体以字符串形式给出)。priority (int) – 请求的优先级(默认为
0
)。调度程序使用优先级来定义处理请求的顺序。优先级值较高的请求将更早执行。允许使用负值来表示相对较低的优先级。dont_filter (bool) – 指示此请求不应由调度程序过滤。当您想要多次执行相同的请求时,用于忽略重复项过滤器。谨慎使用,否则会导致抓取循环。默认为
False
。errback (collections.abc.Callable) –
如果在处理请求期间引发任何异常,则将调用此函数。这包括使用 404 HTTP 错误等失败的页面。它接收一个
Failure
作为第一个参数。有关更多信息,请参见下面的 使用 errback 捕获请求处理中的异常。版本 2.0 中的更改: 当指定了 errback 参数时,不再需要 callback 参数。
flags (list) – 发送到请求的标志,可用于日志记录或类似目的。
cb_kwargs (dict) – 一个包含任意数据的字典,这些数据将作为关键字参数传递给 Request 的回调。
- url¶
包含此请求 URL 的字符串。请记住,此属性包含转义的 URL,因此它可能与在
__init__
方法中传递的 URL 不同。此属性为只读。若要更改 Request 的 URL,请使用
replace()
。
- method¶
表示请求中 HTTP 方法的字符串。保证此字符串为大写。例如:
"GET"
、"POST"
、"PUT"
等。
- headers¶
包含请求头的类似字典的对象。
- meta = {}¶
请求的任意元数据的字典。
您可以根据需要扩展请求元数据。
还可以通过响应的
meta
属性访问请求元数据。若要将数据从一个 spider 回调传递到另一个 spider 回调,请考虑使用
cb_kwargs
。但是,在某些情况下,请求元数据可能是正确的选择,例如在所有后续请求中维护一些调试数据(例如源 URL)。请求元数据的一个常见用法是为 Scrapy 组件(扩展、中间件等)定义请求特定的参数。例如,如果您将
dont_retry
设置为True
,即使请求失败,RetryMiddleware
也不会重试该请求。请参阅 Request.meta 特殊键。您也可以在自定义 Scrapy 组件中使用请求元数据,例如,保留与您的组件相关的请求状态信息。例如,
RetryMiddleware
使用retry_times
元数据键来跟踪到目前为止已重试请求的次数。将先前请求的所有元数据复制到 spider 回调中的新后续请求是一种不好的做法,因为请求元数据可能包含由 Scrapy 组件设置的元数据,这些元数据不应复制到其他请求中。例如,将
retry_times
元数据键复制到后续请求中可能会降低这些后续请求允许的重试次数。只有当新请求旨在替换旧请求时,才应将所有请求元数据从一个请求复制到另一个请求,这在从 下载器中间件 方法返回请求时经常发生。
- cb_kwargs¶
包含此请求的任意元数据的字典。其内容将作为关键字参数传递给 Request 的回调。对于新的 Request,它为空,这意味着默认情况下,回调仅将
Response
对象作为参数。使用
copy()
或replace()
方法克隆请求时,此字典将被 浅复制,并且也可以在您的 spider 中从response.cb_kwargs
属性访问它。如果请求处理失败,则可以在请求的 errback 中将其作为
failure.request.cb_kwargs
访问。有关更多信息,请参阅 在 errback 函数中访问其他数据。
- 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_kwargs
和Request.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
来调用此方法。注意
使用
from_curl()
来自Request
子类,例如JsonRequest
或XmlRpcRequest
,以及启用 下载器中间件 和 蜘蛛中间件,例如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
留给与中间件和扩展等组件的通信。
使用错误回调捕获请求处理中的异常¶
请求的错误回调是一个函数,当在处理请求时引发异常时将调用该函数。
它接收一个 Failure
作为第一个参数,可用于跟踪连接建立超时、DNS 错误等。
这是一个记录所有错误并在需要时捕获某些特定错误的 spider 示例
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
]
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)
在错误回调函数中访问额外数据¶
如果请求处理失败,您可能希望访问回调函数的参数,以便根据 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"],
)
请求指纹¶
在某些抓取方面,例如过滤掉重复请求(参见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哈希值。另请参阅
REQUEST_FINGERPRINTER_IMPLEMENTATION
.
编写您自己的请求指纹生成器¶
请求指纹生成器是一个必须实现以下方法的类
- fingerprint(self, request)¶
返回一个
bytes
对象,该对象唯一标识request。另请参阅请求指纹限制。
- 参数:
request (scrapy.http.Request) – 要生成指纹的请求
此外,它还可以实现以下方法
- classmethod from_crawler(cls, crawler)
如果存在,则调用此类方法以从
Crawler
对象创建请求指纹生成器实例。它必须返回请求指纹生成器的新实例。crawler提供了对所有 Scrapy 核心组件(如设置和信号)的访问;它是请求指纹生成器访问它们并将其实现挂接到 Scrapy 的一种方式。
- 参数:
crawler (
Crawler
对象) – 使用此请求指纹生成器的爬虫
默认请求指纹生成器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 参数,它是一个要包含的请求标头的列表。
此外,服务器在处理请求时通常会忽略 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]
如果需要能够覆盖来自 Spider 回调的任意请求的请求指纹生成,则可以实现一个请求指纹生成器,当可用时从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 相同的指纹生成算法,而不使用REQUEST_FINGERPRINTER_IMPLEMENTATION
设置的已弃用值'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
内部,将创建以下目录结构Spider.name
请求指纹第一个字节的十六进制表示
指纹的十六进制表示
文件名最长 16 个字符。
例如,如果请求指纹由 20 个字节组成(默认值),
HTTPCACHE_DIR
为'/home/user/project/.scrapy/httpcache'
,并且您的 Spider 的名称为'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 消息通过网络发送)到获取响应所花费的时间。此元键仅在下载响应后可用。虽然大多数其他元键用于控制 Scrapy 的行为,但此元键应该只读。
download_fail_on_dataloss¶
是否在出现损坏的响应时失败。请参阅:DOWNLOAD_FAIL_ON_DATALOSS
。
max_retry_times¶
此元键用于设置每个请求的重试次数。max_retry_times
元键初始化后,优先级高于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
子类的列表。您也可以对其进行子类化以实现自己的自定义功能。
FormRequest 对象¶
FormRequest 类扩展了基本Request
,并具有处理 HTML 表单的功能。它使用lxml.html 表单 从Response
对象中使用表单数据预填充表单字段。
- class scrapy.http.request.form.FormRequest¶
- class scrapy.http.FormRequest¶
- class scrapy.FormRequest(url[, formdata, ...])¶
FormRequest
类向__init__
方法添加了一个新的关键字参数。其余参数与Request
类相同,此处不再赘述。- 参数:
formdata(dict 或 collections.abc.Iterable)– 是一个字典(或 (键,值) 元组的可迭代对象),其中包含将进行 URL 编码并分配给请求正文的 HTML 表单数据。
FormRequest
对象除了标准Request
方法外,还支持以下类方法- classmethod FormRequest.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 及更高版本中修复),因此使用此方法处理选项值开头或结尾处有空格的 select 元素将不起作用。
- 参数:
response(
Response
对象)– 包含将用于预填充表单字段的 HTML 表单的响应formname(str)– 如果给出,则将使用名称属性设置为此值的表单。
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
- 参数:
data (object) – 是任何需要 JSON 编码并分配给主体的 JSON 可序列化对象。如果提供了
Request.body
参数,则将忽略此参数。如果未提供Request.body
参数且提供了 data 参数,则Request.method
将自动设置为'POST'
。dumps_kwargs (dict) – 将传递给基础
json.dumps()
方法的参数,该方法用于将数据序列化为 JSON 格式。
- 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)
响应对象¶
- class scrapy.http.Response(*args: Any, **kwargs: Any)[source]¶
表示 HTTP 响应的对象,通常由(下载器)下载并馈送到蜘蛛进行处理。
- 参数:
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¶
一个类似字典的对象,包含响应头。可以使用
get()
访问值以返回具有指定名称的第一个头值,或使用getlist()
返回具有指定名称的所有头值。例如,此调用将为您提供标头中的所有 Cookieresponse.headers.getlist('Set-Cookie')
- body¶
响应正文,以字节形式表示。
如果希望将正文作为字符串,请使用
TextResponse.text
(仅在TextResponse
及其子类中可用)。此属性为只读属性。要更改响应的正文,请使用
replace()
。
- request¶
生成此响应的
Request
对象。此属性由 Scrapy 引擎在响应和请求通过所有 下载器中间件 后分配。特别是,这意味着HTTP 重定向将从重定向前的请求创建一个新请求。它具有大部分相同的元数据和原始请求属性,并分配给重定向的响应,而不是传播原始请求。
Response.request.url 不总是等于 Response.url
此属性仅在蜘蛛代码和 蜘蛛中间件 中可用,在下载器中间件中不可用(尽管您可以通过其他方式在其中获得请求)以及
response_downloaded
信号的处理程序中不可用。
- meta¶
到
Request.meta
属性(即self.request.meta
)的快捷方式。与
Response.request
属性不同,Response.meta
属性在重定向和重试期间会传播,因此您将获得从蜘蛛发送的原始Request.meta
。另请参阅
Request.meta
属性
- cb_kwargs¶
版本 2.0 中新增。
到
Request.cb_kwargs
属性(即self.request.cb_kwargs
)的快捷方式。与
Response.request
属性不同,Response.cb_kwargs
属性在重定向和重试期间会传播,因此您将获得从蜘蛛发送的原始Request.cb_kwargs
。另请参阅
- flags¶
包含此响应标志的列表。标志是用于标记响应的标签。例如:
'cached'
、'redirected
’ 等。它们显示在响应的字符串表示形式(__str__ 方法)上,引擎使用该字符串表示形式进行日志记录。
- certificate¶
版本 2.0.0 中新增。
一个表示服务器 SSL 证书的
twisted.internet.ssl.Certificate
对象。仅在
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 或scrapy.link.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
类则提供了。通过查看响应体推断出的编码。这是一种更脆弱的方法,但也是最后尝试的一种。
- 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.[*]')
- 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
一个
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
一个
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
属性的锚标记)
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 类型 时使用。