请求和响应¶
Scrapy使用 Request
和 Response
对象来抓取网站。
通常,Request
对象在蜘蛛程序中生成,并传递到系统,直到它们到达下载程序,该程序执行请求并返回 Response
对象,该对象返回到发出请求的蜘蛛程序。
Request
和 Response
类都具有添加基类中不需要的功能的子类。这些在下面的 请求子类 和 响应子类 中描述。
请求对象¶
-
class
scrapy.http.
Request
(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback])¶ Request
对象表示HTTP请求,它通常在Spider中生成并由下载程序执行,从而生成Response
。参数: - url (string) – 此请求的URL
- callback (callable) – 将使用此请求的响应(一旦其下载)作为其第一个参数调用的函数。有关更多信息,请参阅下面的 将附加数据传递给回调函数。如果请求没有指定回调,将使用蜘蛛的
parse()
方法。请注意,如果在处理期间引发异常,则会调用errback。 - method (string) – 此请求的HTTP方法。默认为
'GET'
。 - meta (dict) –
Request.meta
属性的初始值。如果给定的,在这个参数传递的字典将是浅复制。 - body (str or unicode) – 请求体。如果传递
unicode
,则使用传递的 encoding (其默认为utf-8
)将其编码到str
。如果未给出body
,则存储一个空字符串。无论此参数的类型如何,存储的最终值将是str
(从不是unicode
或None
)。 - headers (dict) – 此请求的标头。 dict值可以是字符串(对于单值标头)或列表(对于多值标头)。如果
None
作为值传递,则不会发送HTTP头。 - cookies (dict or list) – 请求cookie。这些可以以两种形式发送。 1. 使用dict:: 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的
domain
和path
属性。这只有在保存Cookie用于以后的请求时才有用。当某些网站返回Cookie(在响应中)时,这些Cookie会存储在该域的Cookie中,并在将来的请求中再次发送。这是任何常规网络浏览器的典型行为。但是,如果由于某些原因,您想要避免与现有Cookie合并,您可以指示Scrapy这样做,方法是在Request.meta
中将dont_merge_cookies
键设置为True。不合并Cookie的请求示例:: request_with_cookies = Request(url=”http://www.example.com”, cookies={‘currency’: ‘USD’, ‘country’: ‘UY’}, meta={‘dont_merge_cookies’: True}) 更多信息见 Cookie中间件。 - encoding (string) – 此请求的编码(默认为
'utf-8'
)。此编码将用于对URL进行百分比编码,并将正文转换为str
(如果以unicode
形式提供)。 - priority (int) – 此请求的优先级(默认为
0
)。调度器使用优先级来定义用于处理请求的顺序。具有较高优先级值的请求将较早执行。允许负值以指示相对低优先级。 - dont_filter (boolean) – 表示此请求不应由调度程序过滤。当您想要多次执行相同的请求时忽略重复过滤器时使用。小心使用它,或者你会进入爬行循环。默认为
False
。 - errback (callable) – 如果在处理请求时引发任何异常,将调用的函数。这包括失败的404 HTTP错误等页面。它接收 Twisted Failure 实例作为第一个参数。有关详细信息,请参阅下面的 使用errbacks在请求处理中捕获异常。
-
method
¶ 表示请求中的HTTP方法的字符串。这保证是大写的。示例:
"GET"
,"POST"
,"PUT"
等
-
headers
¶ 包含请求标头的类似字典的对象。
-
meta
¶ 包含此请求的任意元数据的字典。此dict对于新请求为空,通常由不同的Scrapy组件(扩展程序,中间件等)填充。因此,此dict中包含的数据取决于您启用的扩展。
有关Scrapy识别的特殊元键列表,请参阅 Request.meta特殊键。
当使用
copy()
或replace()
方法克隆请求时,此dict是 shallow copied,也可以在您的蜘蛛中从response.meta
属性访问。
-
copy
()¶ 返回一个新的请求,它是这个请求的副本。参见:将附加数据传递给回调函数。
-
replace
([url, method, headers, body, cookies, meta, encoding, dont_filter, callback, errback])¶ 返回具有相同成员的Request对象,但通过指定的任何关键字参数赋予新值的成员除外。默认情况下复制属性
Request.meta
(除非在meta
参数中给出新值)。参见 将附加数据传递给回调函数。
将附加数据传递给回调函数¶
请求的回调是当下载该请求的响应时将被调用的函数。将使用下载的 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.meta
属性。
下面是一个使用此机制传递项目以填充不同页面的不同字段的示例:
def parse_page1(self, response):
item = MyItem()
item['main_url'] = response.url
request = scrapy.Request("http://www.example.com/some_page.html",
callback=self.parse_page2)
request.meta['item'] = item
yield request
def parse_page2(self, response):
item = response.meta['item']
item['other_url'] = response.url
yield item
使用errbacks在请求处理中捕获异常¶
请求的errback是在处理异常时被调用的函数。
它接收 Twisted 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
"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特殊键¶
Request.meta
属性可以包含任何任意数据,但是有一些由Scrapy及其内置扩展识别的特殊键。
那些是:
dont_merge_cookies
(参见Request
构造函数的cookies
参数)
bindaddress¶
用于执行请求的出站IP地址的IP。
download_timeout¶
下载器在超时前等待的时间量(以秒为单位)。参见:DOWNLOAD_TIMEOUT
。
download_latency¶
自请求已启动以来,用于获取响应的时间量,即通过网络发送的HTTP消息。此元键仅在响应已下载时可用。虽然大多数其他元键用于控制Scrapy行为,但这应该是只读的。
请求子类¶
这里是内置的 Request
子类的列表。您还可以将其子类化以实现您自己的自定义功能。
FormRequest对象¶
FormRequest类扩展了具有处理HTML表单的功能的基本 Request
。它使用 lxml.html forms 通过 Response
对象的表单数据预填充表单字段。
-
class
scrapy.http.
FormRequest
(url[, formdata, ...])¶ FormRequest
类向构造函数添加一个新参数。其余的参数与Request
类相同,这里没有记录。参数: formdata (dict or iterable of tuples) – 是一个包含HTML表单数据的字典(或((key,value)元组的迭代),它将被url编码并分配给请求的主体。 除了标准
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
参数。参数: - response (
Response
object) – 该响应包含将用于预填充表单字段的HTML表单 - formname (string) – 如果给定,将使用具有设置为此值的name属性的形式。
- formid (string) – 如果给定,将使用具有设置为此值的id属性的形式。
- formxpath (string) – 如果给定,将使用与xpath匹配的第一个表单。
- formcss (string) – 如果给定,将使用与css选择器匹配的第一个表单。
- formnumber (integer) – 要使用的表单的数量,当响应包含多个表单时。第一个(也是默认值)是
0
。 - formdata (dict) – 字段在表单数据中覆盖。如果响应
<form>
元素中已存在字段,则其值将被在此参数中传递的值覆盖。 - clickdata (dict) – 属性来查找单击的控件。如果没有提供,表单数据将被提交,模拟第一个可点击元素的点击。除了html属性,控件可以通过其相对于窗体中其他提交表输入的基于零的索引,通过
nr
属性来标识。 - dont_click (boolean) – 如果为True,表单数据将在不点击任何元素的情况下提交。
此类方法的其他参数直接传递到
FormRequest
构造函数。0.10.3 新版功能:
formname
参数。0.17 新版功能:
formxpath
参数。1.1.0 新版功能:
formcss
参数。1.1.0 新版功能:
formid
参数。- response (
-
classmethod
请求使用示例¶
使用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
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):
# check login succeed before going on
if "authentication failed" in response.body:
self.logger.error("Login failed")
return
# continue scraping with authenticated session...
响应对象¶
-
class
scrapy.http.
Response
(url[, status=200, headers=None, body=b'', flags=None, request=None])¶ Response
对象表示HTTP响应,通常由Downloader下载并馈送给Spiders进行处理。参数: - url (string) – 此响应的URL
- status (integer) – 响应的HTTP状态。默认为
200
。 - headers (dict) – 此响应的标题。 dict值可以是字符串(对于单值标头)或列表(对于多值标头)。
- body (str) – 响应体。它必须是str,而不是unicode,除非你使用编码感知的 响应子类,如
TextResponse
。 - flags (list) – 是包含
Response.flags
属性的初始值的列表。如果给定,列表将被浅复制。 - request (
Request
object) –Response.request
属性的初始值。这表示产生此响应的Request
。
-
status
¶ 表示响应的HTTP状态的整数。示例:
200
,404
。
-
headers
¶ 包含响应标题的类字典对象。可以使用
get()
访问值以返回具有指定名称的第一个标头值或getlist()
,以返回具有指定名称的所有标头值。例如,此调用将为您提供标题中的所有Cookie:response.headers.getlist('Set-Cookie')
-
body
¶ 本回复的正文。记住Response.body总是一个字节对象。如果你想unicode版本使用
TextResponse.text
(只在TextResponse
和子类中可用)。此属性为只读。要更改响应的主体,请使用
replace()
。
-
request
¶ 生成此响应的
Request
对象。此属性在Scrapy引擎中分配,在响应和请求通过所有 下载中间件 后。特别地,这意味着:HTTP重定向将导致将原始请求(重定向之前的URL)分配给重定向响应(重定向后具有最终URL)。
Response.request.url并不总是等于Response.url
此属性仅在蜘蛛程序代码和 蜘蛛中间件 中可用,但不能在下载中间件(虽然您有通过其他方式可用的请求)和
response_downloaded
信号的处理程序。
-
meta
¶ Response.request
对象(即self.request.meta
)的Request.meta
属性的快捷方式。与
Response.request
属性不同,Response.meta
属性沿重定向和重试传播,因此您将获得从您的蜘蛛发送的原始Request.meta
。参见
Request.meta
属性
-
flags
¶ 包含此响应的标志的列表。标志是用于标记响应的标签。例如:‘cached’,‘redirected‘等。它们显示在由引擎用于记录的Response(__str__ 方法)的字符串表示上。
-
copy
()¶ 返回一个新的响应,它是此响应的副本。
-
replace
([url, status, headers, body, request, flags, cls])¶ 返回具有相同成员的Response对象,但通过指定的任何关键字参数赋予新值的成员除外。默认情况下将复制属性
Response.meta
。
-
urljoin
(url)¶ 通过将响应的
url
与可能的相对URL组合构造绝对url。这是 urlparse.urljoin 的一个包装,它只是一个别名来进行这个调用:
urlparse.urljoin(response.url, url)
响应子类¶
下面是可用的内置Response子类的列表。您还可以将Response类子类化以实现您自己的功能。
TextResponse对象¶
-
class
scrapy.http.
TextResponse
(url[, encoding[, ...]])¶ TextResponse
对象向基本Response
类添加编码能力,这意味着仅用于二进制数据,例如图像,声音或任何媒体文件。除了基本的
Response
对象之外,TextResponse
对象还支持新的构造函数参数。其余功能与Response
类相同,在此不作说明。参数: encoding (string) – 是一个字符串,其中包含用于此响应的编码。如果您创建一个具有unicode主体的 TextResponse
对象,它将使用此编码进行编码(记住body属性总是一个字符串)。如果encoding
是None
(默认值),则将在响应头和正文中查找编码。除了标准
Response
对象之外,TextResponse
对象还支持以下属性:-
text
¶ 响应体,如unicode。
与
response.body.decode(response.encoding)
相同,但是结果在第一次调用后缓存,因此您可以多次访问response.text
,而无需额外的开销。注解
unicode(response.body)
不是将响应主体转换为unicode的正确方法:您将使用系统默认编码(通常为 ascii)而不是响应编码。
-
encoding
¶ 包含此响应的编码的字符串。编码通过尝试以下机制按顺序解决:
在构造函数 encoding 参数中传递的编码
在Content-Type HTTP头中声明的编码。如果此编码无效(即未知),则会被忽略,并尝试下一个解析机制。
在响应主体中声明的编码。 TextResponse类不提供任何特殊功能。然而,
HtmlResponse
和XmlResponse
类做的。通过查看响应体来推断的编码。这是更脆弱的方法,但也是最后一个尝试。
除了标准
Response
对象之外,TextResponse
对象还支持以下方法:-
xpath
(query)¶ TextResponse.selector.xpath(query)
的快捷方式:response.xpath('//p')
-
css
(query)¶ TextResponse.selector.css(query)
的快捷方式:response.css('p')
-
HtmlResponse对象¶
-
class
scrapy.http.
HtmlResponse
(url[, ...])¶ HtmlResponse
类是TextResponse
的子类,通过查看HTML meta http-equiv 属性来添加编码自动发现支持。见TextResponse.encoding
。
XmlResponse对象¶
-
class
scrapy.http.
XmlResponse
(url[, ...])¶ XmlResponse
类是TextResponse
的子类,通过查看XML声明行来添加编码自动发现支持。参见TextResponse.encoding
。