Scrapy 简明教程

Scrapy - Requests and Responses

Description

Scrapy 可使用 RequestResponse 对象抓取网站。请求对象经过系统,使用蜘蛛执行请求并在返回响应对象时返回到请求。

Request Objects

请求对象是一个生成响应的 HTTP 请求。它具有以下类:

class scrapy.http.Request(url[, callback, method = 'GET', headers, body, cookies, meta,
   encoding = 'utf-8', priority = 0, dont_filter = False, errback])

下表显示请求对象的各个参数:

Sr.No

Parameter & Description

1

url 是一个指定 URL 请求的字符串。

2

callback 是一个可调用函数,该函数将请求的响应用作第一个参数。

3

method 是一个指定 HTTP 方法请求的字符串。

4

headers 是一个具有请求头部的词典。

5

body 是一个具有请求正文的字符串或 unicode。

6

cookies 是一个包含请求 cookie 的列表。

7

meta 是一个包含请求元数据值的词典。

8

encoding 是一个包含用于对 URL 编码的 utf-8 编码的字符串。

9

priority 是一个整型,其中调度程序使用优先级来定义处理请求的顺序。

10

dont_filter 是一个布尔值,指定调度程序不得过滤该请求。

11

errback 是一个可调用函数,在处理请求时引发异常时调用。

Passing Additional Data to Callback Functions

请求的回调函数在以其第一个参数下载响应时调用。

例如 -

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

Using errbacks to Catch Exceptions in Request Processing

当在处理请求时引发异常时,调用 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 Special Keys

request.meta 特殊键是 Scrapy 识别的特殊 meta 键列表。

下表显示 Request.meta 的一些键:

Sr.No

Key & Description

1

dont_redirect 当设置为 true 时,这是一个关键,不依据响应的状态重新定向请求。

2

dont_retry 当设置为 true 时,这是一个关键,不会重试失败的请求,并且会被中间件忽略。

3

handle_httpstatus_list 这是一个定义每个请求基础允许哪些响应代码的关键。

4

handle_httpstatus_all 这是一个关键,用于通过将其设置为 true 来允许任何请求响应代码。

5

dont_merge_cookies 这是一个关键,用于通过将其设置为 true 来避免与现有 cookie 合并。

6

cookiejar 这是一个关键,用于为每个蜘蛛保持多个 cookie 会话。

7

dont_cache 这是一个关键,用于避免在每个策略上缓存 HTTP 请求和响应。

8

redirect_urls 这是一个关键,包含请求通过的 URL。

9

bindaddress 这是可用于执行请求的传出 IP 地址的 IP。

10

dont_obey_robotstxt 当设置为 true 时,这是一个关键,即使启用了 ROBOTSTXT_OBEY,也不会过滤 robots.txt 排除标准禁止的请求。

11

download_timeout 它用于为每个蜘蛛设置超时(以秒为单位),下载器将在超时之前等待此超时。

12

download_maxsize 它用于为每个蜘蛛设置最大大小(以字节为单位),这是下载器将下载的大小。

13

可以针对 Request 对象设置代理,以将 HTTP 代理设置为用于请求。

Request Subclasses

你可以通过对 request 类进行子类化来实现自己的自定义功能。内置请求子类如下 −

FormRequest Objects

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 表单数据的字典,该字典被分配给请求正文。

Note − 其余参数与 request 类相同,并在 Request Objects 部分中进行了说明。

除了请求方法之外, FormRequest 对象还支持以下类方法 −

classmethod from_response(response[, formname = None, formnumber = 0, formdata = None,
   formxpath = None, formcss = None, clickdata = None, dont_click = False, ...])

下表显示了上面类的参数 -

Sr.No

Parameter & Description

1

response 这是一个用于使用 HTML 表单响应预先填充表单字段的对象。

2

formname 如果指定,这是一个将使用名称属性的表单的字符串。

3

formnumber 当响应中有多个表单时,这是一个要使用的表单的整数。

4

formdata 这是一个用于覆盖的表单数据字段的字典。

5

formxpath 当指定时,这是使用 xpath 匹配的表单。

6

formcss 当指定时,这是使用 css 选择器匹配的表单。

7

clickdata 这是一个用于观察已单击控件的属性字典。

8

dont_click 当设置为 true 时,表单中的数据将被提交且不会单击任何元素。

Examples

以下是部分请求用例 -

Using FormRequest to send data via HTTP POST

下面的代码演示了在蜘蛛中重复 HTML 表单 POST 时,如何返回 FormRequest 对象 -

return [FormRequest(url = "http://www.something.com/post/action",
   formdata = {'firstname': 'John', 'lastname': 'dave'},
   callback = self.after_post)]

Using FormRequest.from_response() to simulate a user login

通常,网站使用元素通过它们提供预先填充的表单字段。

当你希望这些字段在抓取时自动填充时,可以使用 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

Response Objects

这是一个表征 HTTP 响应的对象,它被输入到需要处理的爬虫中。它有以下类 -

class scrapy.http.Response(url[, status = 200, headers, body, flags])

下表显示了响应对象的参数 -

Sr.No

Parameter & Description

1

url 这是一个指定 URL 响应字符串。

2

status 这是一个包含 HTTP 状态响应的整数。

3

headers 这是包含响应头的字典。

4

body 这是一个包含响应体的字符串。

5

flags 这是一个包含响应标志的列表。

Response Subclasses

你可以通过对响应类进行子类化来实现你自定义的功能。内置的响应子类如下:

TextResponse objects

TextResponse 对象被用于二进制数据,例如图像、声音等,它有能力编码基本的响应类。它包含以下类:

class scrapy.http.TextResponse(url[, encoding[,status = 200, headers, body, flags]])

以下是参数 −

encoding − 这是一个用于对响应进行编码的字符串。

Note − 剩余的参数与响应类相同,在 Response Objects 部分中对其进行了说明。

下表显示了 TextResponse 对象在响应方法之外支持的属性:

Sr.No

Attribute & Description

1

text 这是一个响应体,可以多次访问 response.text。

2

encoding 这是一个包含用于响应的编码的字符串。

3

selector 这是一个在首次访问时实例化的属性,并且使用响应作为目标。

下表显示了 TextResponse 对象在响应方法之外支持的方法:

Sr.No

Method & Description

1

xpath (query) 这是一个指向 TextResponse.selector.xpath(query) 的捷径。

2

css (query) 这是一个指向 TextResponse.selector.css(query) 的捷径。

3

body_as_unicode() 这是一个响应体,可以作为一种方法进行访问,在其中可以多次访问 response.text。

HtmlResponse Objects

它是一个支持编码和自动发现的对象,通过查看 HTML 的 meta httpequiv 属性进行此操作。它的参数与响应类相同,在响应对象部分中对此进行了说明。它包含以下类:

class scrapy.http.HtmlResponse(url[,status = 200, headers, body, flags])

XmlResponse Objects

它是一个通过查看 XML 行支持编码和自动发现的对象。它的参数与响应类相同,在响应对象部分中对此进行了说明。它包含以下类:

class scrapy.http.XmlResponse(url[, status = 200, headers, body, flags])