目录
1. Scrapy功能扩展
- 下载中间件
- 设置随机请求头
2. Scrapy实用技巧
- Scrapy模拟登录
- 内置模块下载图片
课堂笔记
1. Scrapy功能扩展
1.1 下载中间件
-
下载中间件(Download Middlewares):可修改爬取过程中的request和response,扩展scrapy的功能。
-
Download Middlewares默认方法
# 当每个request通过下载中间件时,该方法被调用 def process_request(self, request, spider): return None # 当下载器完成http请求,传递响应给引擎的时候调用 def process_response(self, request, response, spider): return response
-
process_request()方法
- 当每个request请求经过下载中间件时,会根据优先级高而先调用的特点调用。
- 返回值:None、request对象、response对象以及Ignore Request异常。
- 返回None:scrapy会依次继续执行其他中间件相应方法。
- 返回request对象:scrapy不会再执行其他中间件的process_request方法,而是将其放置在调度器等待下载。
- 返回response对象:与返回request对象类似,但是不会发起下载,而且是直接返回该response对象。
- 返回Ignore Request异常:会自动调用process_exception方法。
-
process_response()方法
- 当每个response响应经过下载中间件时,会根据优先度高而后调用的特点进行调用。
- 返回值:request对象、response对象以及Ignore Request异常。
- 返回request对象:停止中间件调用,将其放置到调度器待调度下载。
- 返回response对象:scrapy会继续调用其他中间件的process_response方法。
- 返回Ignore Request异常:Request.errback会被调用来处理函数,如果没有处理,它将会被忽略且不会写进日志。
1.2 设置随机请求头
-
为防止过多次数使用同一个请求头而被反爬,可以在下载中间件中进行随机请求头的获取,从而降低被反爬的概率。
-
设置随机请求头:
- 在setting模块中配置User-Agent参数;
USER_AGENTS = [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5" ]
- 在下载中间件的process_request方法中设置随机请求头。
import random def process_request(self, request, spider): request.headers['User-Agent'] = random.choice(self.settings['USER_AGENTS']) return None def process_response(self, request, response, spider): print(request.headers['User-Agent']) return response
2. Scrapy实用技巧
2.1 Scrapy模拟登录
-
scrapy实现登录方式:
-
携带cookies登录;
class CsdnSpider(scrapy.Spider): name = 'csdn' allowed_domains = ['mp.csdn.net'] start_urls = ['https://blog.csdn.net/qq_43407841/article/details/107473507'] cookies='xxx' # 重写Spider类的start_requests方法 def start_requests(self): # 使用字典推导式,将原cookies修改成key:value的格式保存到字典 cookies = {d.split('=')[0] : d.split('=')[1] for d in self.cookies.split('; ')} # 指定参数 yield scrapy.Request( url=self.start_urls[0], callback=self.parse, cookies=cookies ) def parse(self, response): # 将获取的源代码写入html文档 with open('csdn.html', 'w', encoding='utf-8') as f: f.write(response.body.decode())
-
以post方式,提交from表单登录。
class GithubSpider(scrapy.Spider): name = 'github' allowed_domains = ['github.com'] start_urls = ['https://github.com/login'] def parse(self, response): yield scrapy.FormRequest.from_response( # 提交的响应结果 response=response, # 回调函数 callback=self.login_page, # 提交参数 formdata={'login':'username', 'password':'password'} ) def login_page(self, response): with open('github.html', 'w', encoding='utf-8') as f: f.write(response.body.decode())
-
2.2 内置模块下载图片
-
下载文件的 Files Pipeline
- 定义好一个Item,然后在这个item中定义两个属性,分别为file_urls以及files。files_urls是用来存储需要下载的文件的url链接,需要给一个列表;
- 当文件下载完成后,会把文件下载的相关信息存储到item的files属性中。如下载路径、下载的url和文件校验码等;
- 在配置文件settings.py中配置FILES_STORE,这个配置用来设置文件下载路径;
- 启动pipeline:在ITEM_PIPELINES中设置scrapy.piplines.files.FilesPipeline:1。
-
下载图片的 Images Pipeline
- 定义好一个Item,然后在这个item中定义两个属性,分别为image_urls以及images。image_urls是用来存储需要下载的文件的url链接,需要给一个列表;
- 当文件下载完成后,会把文件下载的相关信息存储到item的images属性中。如下载路径、下载的url和图片校验码等;
- 在配置文件settings.py中配置IMAGES_STORE,这个配置用来设置文件下载路径;
- 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline:1。
-
内置下载模块优势
- 避免重新下载最近已经下载过的数据。
- 可以方便的指定文件存储的路径。
- 可以将下载的图片转换成通用的格式。如:png、jpg。
- 可以方便的生成缩略图。
- 可以方便的检测图片的宽和高,确保他们满足最小限制。
- 异步下载,效率非常高。
-
动态设置下载文件路径:
import os # 获取当前文件的路径 print(__file__) # 获取上一级路径 print(os.path.dirname(__file__)) # 获取上上一级路径 print(os.path.dirname(os.path.dirname(__file__))) # 连接path1与path2 os.path.join(path1, path2)