下载器中间件,请求和响应

时间:2018-07-04 00:34:11

标签: scrapy

我知道中间件将请求传递给Downloader,然后将响应传递给Spider,但是没有任何东西可以解释应该使用Downloader Middleware做什么,而且我在任何地方都找不到合适的解释。

它的目的是什么? Downloader Middleware用于修改请求和响应的方式有哪些? Downloader Middleware是否用于处理异常,管理代理和用户代理字符串等?

1 个答案:

答案 0 :(得分:2)

让我们举个例子,因为它是草率的文档

import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"

    start_urls = [
        'http://quotes.toscrape.com/page/1/',
        'http://quotes.toscrape.com/page/2/',
    ]

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').extract_first(),
                'author': quote.css('small.author::text').extract_first(),
                'tags': quote.css('div.tags a.tag::text').extract(),
            }

效果很好,但是您已经知道并非所有网站(例如amazon.com)都是如此

您需要在请求标头中发送用户代理(如Mozilla或Chrome),这样它才能知道请求来自浏览器。您可以通过替换USER_AGENT =“ Mozilla / 5.0(X11; Linux x86_64)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 51.0.2704.103 Safari / 537.36”来轻松更改设置。

现在,您已经更改了用户代理,亚马逊的服务器将感觉到请求来自chrome浏览器。更进一步,您正在将并发数量增加到100之类的大数。现在发生的事情是,亚马逊可以轻松跟踪您的机器人,并且您将被禁止,因为这意味着单个设备每秒访问服务器100次,这是人类不可能做到的。

因此出现了代理轮换和用户代理轮换。问题是我们如何轮换它们。

假设您的设置中有一堆USER_AGENTS = [...]

middlewares.py     从.settings导入USER_AGENT_LIST     随机导入     从scrapy导入日志中

class UserAgentRotationMiddleware(object):

    def process_request(self, request, spider):
        agent  = random.choice(USER_AGENT_LIST)
        if agent:
            request.headers.setdefault('User-Agent', agent)

而且你必须像这样说一些易碎的项目

DOWNLOADER_MIDDLEWARES = {
   "yourproject.middlewares.UserAgentRotationMiddleware": 500
}

运行蜘蛛程序后会发生什么?

说明:

  1. 草率的日程表请求。
  2. URL在请求到达服务器之前进入下载程序中间件

从技术上讲,它将调用下载程序中间件类,并调用process_request方法并提供当前的请求对象和蜘蛛对象

def process_request(self, request, spider):

现在您可以使用请求对象,您可以使用它执行任何操作,例如更改标头代理甚至url本身。但是我们现在专注于用户代理。

因此,通过我们的算法,我们将更改用户代理,

# Choosing random user agent from a list
agent  = random.choice(USER_AGENT_LIST)
    if agent:
        request.headers.setdefault('User-Agent', agent)

该中间件再次收到新的请求计划,它将更改用户代理,并将请求对象向前传递。

DOWNLOADER_MIDDLEWARES = {
   "yourproject.middlewares.UserAgentRotationMiddleware": 500
}

注册我们的项目时,我们必须指定100到900之间的某个数字, 它表示什么500?(作为中间件名称空间的值)

scrapy中已经存在许多不同的中间件,并且在这种情况下,我们可以根据需要定义许多中间件 如何确定它们的优先级? 它们的执行顺序是什么?

它以升序执行,例如100、200、230、500、650、900。

代理轮换采用相同的方法。

请求:

如果您使用了较低级别的urllib或请求模块,它有什么作用? 它以url作为参数(cookie,代理,标头,有效负载可选参数)

运行它时,它的作用是什么? 它向网址“ http://quotes.toscrape.com”发出http请求

就像通常在浏览器中一样:

  1. 打开浏览器。
  2. 在网址栏中输入“ http://quotes.toscrape.com
  3. 您的浏览器显示该网站

但是在步骤2和3之间还有很多事情要做。 您的浏览器使用较低级别的http请求将url请求发送到服务器。获取响应,然后将其编译下来并显示在浏览器中。

具有相同作用的伪代码

import requests

response = requests.get('http://quotes.toscrape.com')

print response.status_code
print response.content

requests.get到网址“ http://quotes.toscrape.com” 将HTTP GET请求发送到“ http://quotes.toscrape.com”,它会向您返回响应。您可以执行并签出,它将返回一些html给我们不过是一个回复

scrapy只是为了提供其功能而做的事情,就是将这个请求模块包装在scrapy中。HttpResponse的请求和响应模块。

HttpResponse提供了xpath和CSS选择器。

def parse(self, response):
    response.xpath('....')

scrapy框架在此parse方法中提供的响应是HttpResponse的实例,该实例是较低层urllib的响应对象的包装。