Scrapy – 请求和响应
说明
Scrapy可以使用 请求 和 响应 对象抓取网站。请求对象通过系统,使用蜘蛛来执行请求,并在返回一个响应对象时回到请求。
请求对象
请求对象是一个产生响应的HTTP请求。It has the following class −
class scrapy.http.Request(url[, callback, method = 'GET', headers, body, cookies, meta,
   encoding = 'utf-8', priority = 0, dont_filter = False, errback])
下表显示了请求对象的参数。
| 序号 | 参数和描述 | 
|---|---|
| 1 | url 它是一个字符串,用于指定URL请求。 | 
| 2 | **callback ** 它是一个可调用的函数,使用请求的响应作为第一个参数。 | 
| 3 | method 它是一个字符串,用于指定HTTP方法请求。 | 
| 4 | headers 它是一个包含请求头信息的字典。 | 
| 5 | body 它是一个字符串或unicode,有一个请求体。 | 
| 6 | cookies 它是一个包含请求cookies的列表。 | 
| 7 | meta 它是一个字典,包含请求的元数据的值。 | 
| 8 | encoding 它是一个包含用于编码URL的utf-8编码的字符串。 | 
| 9 | priority 它是一个整数,调度器使用优先级来定义处理请求的顺序。 | 
| 10 | dont_filter 它是一个布尔值,指定调度器不应该过滤请求。 | 
| 11 | errback 它是一个可调用的函数,当处理请求时出现异常时被调用。 | 
传递额外的数据给回调函数
一个请求的回调函数在下载响应作为其第一个参数时被调用。
例如 –
def parse_page1(self, response): 
   return scrapy.Request("http://www.something.com/some_page.html", 
      callback = self.parse_page2)  
def parse_page2(self, response): 
   self.logger.info("%s page visited", response.url) 
你可以使用 Request.meta 属性,如果你想把参数传递给可调用的函数,并在第二个回调中接收这些参数,如下例所示
def parse_page1(self, response): 
   item = DemoItem() 
   item['foremost_link'] = response.url 
   request = scrapy.Request("http://www.something.com/some_page.html", 
      callback = self.parse_page2) 
   request.meta['item'] = item 
   return request  
def parse_page2(self, response): 
   item = response.meta['item'] 
   item['other_link'] = response.url 
   return item
使用errback来捕捉请求处理中的异常情况
errback是一个可调用的函数,当处理请求时出现异常时,可以调用该函数。
下面的例子说明了这一点 −
import scrapy  
from scrapy.spidermiddlewares.httperror import HttpError 
from twisted.internet.error import DNSLookupError 
from twisted.internet.error import TimeoutError, TCPTimedOutError  
class DemoSpider(scrapy.Spider): 
   name = "demo" 
   start_urls = [ 
      "http://www.httpbin.org/",              # HTTP 200 expected 
      "http://www.httpbin.org/status/404",    # Webpage not found  
      "http://www.httpbin.org/status/500",    # Internal server error 
      "http://www.httpbin.org:12345/",        # 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('Recieved response from {}'.format(response.url)) 
      # ...  
   def errback_httpbin(self, failure): 
      # logs failures 
      self.logger.error(repr(failure))  
      if failure.check(HttpError): 
         response = failure.value.response 
         self.logger.error("HttpError occurred on %s", response.url)  
      elif failure.check(DNSLookupError): 
         request = failure.request 
         self.logger.error("DNSLookupError occurred on %s", request.url) 
      elif failure.check(TimeoutError, TCPTimedOutError): 
         request = failure.request 
         self.logger.error("TimeoutError occurred on %s", request.url) 
Request.meta特殊键
request.meta特殊键是一个由Scrapy识别的特殊元键的列表。
下表显示了Request.meta的一些键值-
| 序号 | 键值和描述 | 
|---|---|
| 1 | dont_redirect 这是一个键,当设置为true时,不会根据响应的状态重定向请求。 | 
| 2 | dont_retry 当设置为 “true “时,该键不重试失败的请求,并将被中间件忽略。 | 
| 3 | handle_httpstatus_list 它是一个键,定义了每个请求的响应代码可以被允许。 | 
| 4 | handle_httpstatus_all 它是一个键,通过将其设置为 “true “,允许对一个请求的任何响应代码 。 | 
| 5 | dont_merge_cookies 它是一个键,通过设置为 true 来避免与现有的 cookies 合并。 | 
| 6 | cookiejar 它是一个用于在每个蜘蛛上保留多个cookie会话的键。 | 
| 7 | dont_cache 它是一个用来避免在每个策略上缓存HTTP请求和响应的键。 | 
| 8 | redirect_urls 它是一个包含请求经过的URL的键。 | 
| 9 | bindaddress 它是可用于执行请求的出站IP地址的IP。 | 
| 10 | dont_obey_robotstxt 它是一个键,当设置为true时,不会过滤robots.txt排除标准所禁止的请求,即使ROBOTSTXT_OBEY被启用。 | 
| 11 | download_timeout 它用于设置每个蜘蛛的超时时间(秒),在超时之前,下载器会等待。 | 
| 12 | download_maxsize 用来设置每个蜘蛛的最大尺寸(以字节为单位),下载器将会下载。 | 
| 13 | proxy 可以为Request对象设置HTTP代理,用于请求的使用。 | 
请求子类
你可以通过子类化请求类来实现你自己的自定义功能。内置的请求子类如下:
FormRequest对象
FormRequest类通过扩展基础请求来处理HTML表单。它有以下的类 –
class scrapy.http.FormRequest(url[,formdata, callback, method = 'GET', headers, body, 
   cookies, meta, encoding = 'utf-8', priority = 0, dont_filter = False, errback])
以下是参数 –
formdata - 它是一个拥有HTML表单数据的字典,被分配到请求的正文中。
注意 - 其余的参数与请求类相同,在 请求对象 部分有解释。
除了请求方法外, FormRequest 对象还支持以下类方法
classmethod from_response(response[, formname = None, formnumber = 0, formdata = None, 
   formxpath = None, formcss = None, clickdata = None, dont_click = False, ...])
下表显示了上述类别的参数:
| 序号 | 参数和描述 | 
|---|---|
| 1 | **response ** 它是一个对象,用于使用HTML形式的响应预先填充表单字段。 | 
| 2 | formname 它是一个字符串,如果指定的话,将使用具有名称属性的表单。 | 
| 3 | formnumber 当响应中有多个表单时,它是一个表单的整数。 | 
| 4 | formdata 它是用于覆盖的表单数据字段的字典。 | 
| 5 | formxpath 指定时是一个字符串,使用与xpath匹配的表单。 | 
| 6 | formcss 指定时是一个字符串,使用与css选择器匹配的表单。 | 
| 7 | clickdata 它是一个属性字典,用于观察被点击的控件。 | 
| 8 | dont_click 当设置为true时,表单中的数据将在不点击任何元素的情况下被提交。 | 
例子
下面是一些请求使用的例子
使用FormRequest通过HTTP POST发送数据
下面的代码演示了当你想在你的spider中复制HTML表单POST时,如何返回 FormRequest 对象。
return [FormRequest(url = "http://www.something.com/post/action", 
   formdata = {'firstname': 'John', 'lastname': 'dave'}, 
   callback = self.after_post)]
使用FormRequest.from_response()来模拟用户登录
通常情况下,网站使用元素,通过这些元素提供预填充的表单字段。
当你想在搜刮时自动填充这些字段时,可以使用 FormRequest.form_response() 方法。
下面的例子演示了这一点。
import scrapy  
class DemoSpider(scrapy.Spider): 
   name = 'demo' 
   start_urls = ['http://www.something.com/users/login.php']  
   def parse(self, response): 
      return scrapy.FormRequest.from_response( 
         response, 
         formdata = {'username': 'admin', 'password': 'confidential'}, 
         callback = self.after_login 
      )  
   def after_login(self, response): 
      if "authentication failed" in response.body: 
         self.logger.error("Login failed") 
         return  
      # You can continue scraping here
响应对象
它是一个表示HTTP响应的对象,被送至蜘蛛处理。它有以下类别 −
class scrapy.http.Response(url[, status = 200, headers, body, flags])
下表显示了响应对象的参数。
| 序号 | 参数和描述 | 
|---|---|
| 1 | url 这是一个字符串,用于指定URL响应。 | 
| 2 | status 它是一个整数,包含HTTP状态响应。 | 
| 3 | headers 它是一个包含响应头的字典。 | 
| 4 | body 它是一个包含响应主体的字符串。 | 
| 5 | flags 它是一个包含响应标志的列表。 | 
响应子类
你可以通过子类化响应类来实现你自己的自定义功能。内置的响应子类如下。
TextResponse对象
TextResponse对象用于二进制数据,如图像、声音等,它具有对基础Response类进行编码的能力。It has the following class −
class scrapy.http.TextResponse(url[, encoding[,status = 200, headers, body, flags]])
以下是参数 –
encoding - 它是一个带有编码的字符串,用于对响应进行编码。
注意 - 其余的参数与响应类相同,在 响应对象 部分有解释。
下表显示了TextResponse对象在响应方法之外支持的属性-
| 序号 | 属性和描述 | 
|---|---|
| 1 | text 它是一个响应体,其中 response.text 可以被多次访问。 | 
| 2 | encoding 它是一个包含响应编码的字符串。 | 
| 3 | selector 它是一个在第一次访问时实例化的属性,使用响应作为目标。 | 
下表显示了 TextResponse 对象在 响应 方法之外支持的方法-
| 序号 | 方法和描述 | 
|---|---|
| 1 | xpath(query) 它是TextResponse.selector.xpath(query)的一个快捷方式。 | 
| 2 | css (query ) 它是TextResponse.selector.css(query)的快捷方式。 | 
| 3 | body_as_unicode() 它是一个可作为方法的响应体,其中 response.text 可以被多次访问。 | 
HtmlResponse对象
它是一个支持编码的对象,通过查看HTML的 meta httpequiv 属性来自动发现。它的参数与响应类相同,在响应对象部分有解释。它有以下的类 –
class scrapy.http.HtmlResponse(url[,status = 200, headers, body, flags])
XmlResponse对象
它是一个支持编码和通过查看XML行来自动发现的对象。它的参数与响应类相同,在响应对象部分有解释。它有以下的类 –
class scrapy.http.XmlResponse(url[, status = 200, headers, body, flags])
极客教程