目录
def process_spider_input(self, response, spider):
def process_spider_output(self, response, result, spider):
def process_spider_exception(self, response, exception, spider):
def process_start_requests(self, start_requests, spider):
def spider_opened():
程序运行记录,参数 spider 代表项目 spider 文件夹的 spider 程序
def from_crawler(cls, crawler):
访问 setting 和 signals 的入口函数,重写这个方法需要返回实例对象如果返回对象里带有参数,可在 __inti__ 你使用
# 重写__init__
# 参数 MySetting 来自 from_crawler 的返回参数
def __init__(self,MySetting=None)
pass
# 重写 from_crawler
@classmethod
def from_crawler(cls,crawler):
# 从配置文件读取 MySetting 内容
MySetting = crawler.settings.get('MySetting')
# 返回实例对象,并设置参数 MySetting
return cls(MySetting)
def process_spider_input(self, response, spider):
当 response 通过 spider 中间件时,该方法被调用,处理该 response,它应该返回 None 或者抛出一个异常
- 如果返回 None,则 scrapy 会继续处理该 response,调用所有其他中间件直到 spider 处理该 response
- 如果抛出一个异常,则 scrapy 不会调用任何其他中间件的 process_spider_input() 方法,并调用 request 的 errback,
的输出会以另一个方向被重新输入中间件链中,使用 process_spider_output() 方法来处理,当其抛出异常时则调用 process_spider_exception()
def process_spider_output(self, response, result, spider):
当 scrapy 处理 response 返回 result 时,该方法被调用,它必须返回包含 request 或 Item 对象的可迭代对象
- result 参数:包含 request 或 Item 对象的可迭代对象,spider 返回的 result
def process_spider_exception(self, response, exception, spider):
当 spider 或 其他 spider 的中间件 的 process_spider_input() 抛出异常时,被调用,它要么返回 None,要么返回一个包含 response 或 Item 对象的可迭代对象
- 如果返回 None,则 scrapy 继续处理该异常,调用中间键链中的其它中间键的 process_spider_exception() 方法,直到所有中间间都被调用,该异常到达引擎(异常将被记录并忽略)
- 如果返回一个可迭代对象,则中间件链的 process_spider_output() 方法将被调用。其它的 process_spider_exception() 不会被调用
- exception 参数:被抛出的异常
def process_start_requests(self, start_requests, spider):
以 spider 启动的 request 为参数被调用,执行的过程类似于 process_spider_output(),只不过没有关联的 response,并且必须返回的 request(不是Item)
其接受一个可迭代对象,返回另一个包含 request 对象的可迭代对象
内置下载中间件 CookiesMiddleware
几个核心方法
from_crawler
从配置文件中读取 COOKIES_ENABLED,决定是否启用该中间件,如果启用,调用构造器创建对象,否则抛出 NotConfigured 异常,scrapy 件忽略该中间件
__init__
为避免爬虫想同时登陆 cookie 冲突,会让每一个账号发送的 http 请求使用不同的 cookiejar如:
Request(url1,meta={'cookiejar':'account1'})
Request(url2,meta={'cookiejar':'account2'})
proceess_request
处理每一个待发送的 Request 对象,尝试从 request.meta['cookiejar'] 获取用户指定使用的 cookiejar,如果用户未指定,使用默认的 cookiejar(self.jars[None])。调用 self._get_request_cookies 方法发送请求 request 应携带的 cookie 信息,填写到 http 请求头部
process_reponse
处理每一个 Resonse 对象,依然通过 request.meta['cookiejar'] 获取 cookiejar 对象,调用 extract_cookies 方法将http 响应头部中的 cookiejar 信息保存到 cookiejar 对象中
使用浏览器 cookie 的中间件
from scrapy.downloadermiddlewares.cookies import CookiesMiddleware
import browsercookie
class BrowserCookiesMiddleware(CookiesMiddleware):
"""
使用浏览器中的 cookie
"""
def __init__(self,debug=False):
super().__init__(debug)
self.load_browser_cookies()
def load_browser_cookies(self):
#加载 Chrome 浏览器中的 cookie
jar = self.jars['chrome']
chrome_cookiejar = browsercookie.chrome()
for cookie in chrome_cookiejar:
jar.set_cookie(cookie)
- 继承 cookiesmiddleware 并实现构造器方法,在构造器方法中先调用基类的构造器方法,然后调用 self.load_browser_cookies 方法加载浏览器 cookie
- 在 load_browser_cookies 方法中,使用 self.jars['chrome'] 和 self.jars['firefox'] 从默认字典中获得两个 cookiejar 对象,然后调用 browsercookie 的 chrome 和 firefox 方法,分别获取两个浏览器中的 cookie,将他们填入各自的 cookiejar 对象中
从 json 文件中获取随机代理中间件
from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware
from collections import defaultdict
import json
import random
class RandomHttpProxyMiddleware(HttpProxyMiddleware):
"""
随机代理中间件
"""
def __init__(self,auth_encoding='latin-1',proxy_list_file=None):
if not proxy_list_file:
raise NotConfigured
self.auth_encoding = auth_encoding
# 分别用两个列表维护 HTTP 和 HTTPS 的代理,
self.proxies = defaultdict(list)
# 从 json 文件中读取代理服务器信息,填入 self.proxies
with open(proxy_list_file) as f:
proxy_list = json.load(f)
for proxy in proxy_list:
scheme = proxy['proxy_scheme']
url = proxy['proxy']
self.proxies[scheme].append(self._get_proxy(url,scheme))
@classmethod
def from_crawler(cls, crawler):
# 从配置文件中读取用户验证信息的编码
auth_encoding = crawler.settings.get('HTTPPROXY_AUTH_ENCODING','latain-1')
# 从配置文件中读取代理服务器列表文件(json)的路径
proxy_list_file = crawler.settings.get('HTTPPROXY_PROXY_LIST_FILE')
return cls(auth_encoding,proxy_list_file)
def _set_proxy(self, request, scheme):
# 随机选取一个代理
creds,proxy = random.choice(self.proxies[scheme])
request.meta['proxy'] = proxy
if creds:
request.headers['Proxy-Authorization'] = b'Basic' + creds