我知道中间件将请求传递给Downloader,然后将响应传递给Spider,但是没有任何东西可以解释应该使用Downloader Middleware做什么,而且我在任何地方都找不到合适的解释。
它的目的是什么? Downloader Middleware用于修改请求和响应的方式有哪些? Downloader Middleware是否用于处理异常,管理代理和用户代理字符串等?
答案 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
}
运行蜘蛛程序后会发生什么?
说明:
从技术上讲,它将调用下载程序中间件类,并调用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请求
就像通常在浏览器中一样:
但是在步骤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的响应对象的包装。