中间件使用之(UA,IP,selenium)的使用
一.UA池:User-Agent池
- 作用:尽可能多的将scrapy工程中的请求伪装成不同类型的浏览器身份。
- 操作流程:
1.在下载中间件中拦截请求
2.将拦截到的请求的请求头信息中的UA进行篡改伪装
3.在配置文件中开启下载中间件
代码展示:
方法一: #导包 #这个包的位置自己根据自己的scrapy框架的位置来 from scrapy.downloadermiddleware.useragent import UserAgentMiddleware import random #UA池代码的编写(单独给UA池封装一个下载中间件的一个类) class RandomUserAgent(UserAgentMiddleware): def process_request(self, request, spider): #从列表中随机抽选出一个ua值 ua = random.choice(user_agent_list) #ua值进行当前拦截到请求的ua的写入操作 request.headers.setdefault('User-Agent',ua) user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 " "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 " "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 " "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", ] 方法二: 1.安装包: pip install scrapy-fake-useragent 2. 在settings中配置中间件 DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, # 关闭默认方法 'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400, # 开启 } #这样就可以随机抽出一个ua,就不用走第3步了,如果这个不设置,就要走第三步 RANDOM_UA_TYPE= 'random' 3.中间件写入: class RandomUserAgent(object): def process_request(self, request, spider): ua = UserAgent() request.headers['User-Agent'] = ua.random
二.代理池
- 作用:尽可能多的将scrapy工程中的请求的IP设置成不同的。
- 操作流程:
1.在下载中间件中拦截请求
2.将拦截到的请求的IP修改成某一代理IP
3.在配置文件中开启下载中间件
代码展示:
#批量对拦截到的请求进行ip更换 #单独封装下载中间件类 from scrapy import signals import random class MiddleproDownloaderMiddleware(object): # 可被选用的代理IP PROXY_http = [ '153.180.102.104:80', '195.208.131.189:56055', ] PROXY_https = [ '120.83.49.90:9000', '95.189.112.214:35508', ] #拦截所有未发生异常的请求 def process_request(self, request, spider): # 使用代理池进行请求代理ip的设置 # if request.url.split(':')[0] == 'http': # request.meta['proxy'] = random.choice(self.PROXY_http) # else: # request.meta['proxy'] = random.choice(self.PROXY_https) return None #拦截所有的响应 def process_response(self, request, response, spider): return response #拦截到产生异常的请求 def process_exception(self, request, exception, spider): # 使用代理池进行请求代理ip的设置 print('this is process_exception!') if request.url.split(':')[0] == 'http': request.meta['proxy'] = random.choice(self.PROXY_http) else: request.meta['proxy'] = random.choice(self.PROXY_https)
setting.py
DOWNLOADER_MIDDLEWARES = { 'moviePro.middlewares.MovieproDownloaderMiddleware': 543, }
三.selenium
一般情况下,我们在 start_urls 里写好url后,会自动发起get请求,但是这样不好处理动态数据,那么对于动态数据(就是如动态加载,ajax请求之类的数据)我们一般用到自动化工具selenium,直接操作浏览器访问数据得到的响应经过下载器组件与引擎组件之间的中间件(不清楚请看上面的组件运行原理),我们把selenium工具获取的动态数据在中间件中做下处理,然后把数据在返回爬虫文件的parse(response)
案例:访问网易新闻
wangyi.py
import scrapy from selenium import webdriver ''' 在scrapy中使用selenium的编码流程: 1.在spider的构造方法中创建一个浏览器对象(作为当前spider的一个属性) 2.重写spider的一个方法closed(self,spider),在该方法中执行浏览器关闭的操作 3.在下载中间件的process_response方法中,通过spider参数获取浏览器对象 4.在中间件的process_response中定制基于浏览器自动化的操作代码(获取动态加载出来的页面源码数据) 5.实例化一个响应对象,且将page_source返回的页面源码封装到该对象中 6.返回该新的响应对象 7.在配置文件中开启中间件 ''' class WangyiSpider(scrapy.Spider): name = 'wangyi' # allowed_domains = ['www.xxx.com'] start_urls = ['http://war.163.com/'] def __init__(self): self.bro = webdriver.Chrome(executable_path=r'C:\Users\Administrator\Desktop\爬虫+数据\day_03_爬虫\chromedriver.exe') def parse(self, response): div_list = response.xpath('//div[@class="data_row news_article clearfix "]') for div in div_list: title = div.xpath('.//div[@class="news_title"]/h3/a/text()').extract_first() print(title) def closed(self,spider): print('关闭浏览器对象!') self.bro.quit()
middlewares.py
from scrapy import signals from scrapy.http import HtmlResponse from time import sleep class WangyiproDownloaderMiddleware(object):def process_request(self, request, spider): print('即将返回一个新的响应对象!!!') #如何获取动态加载出来的数据 bro = spider.bro bro.get(url=request.url) sleep(3) #包含了动态加载出来的新闻数据 page_text = bro.page_source sleep(3) return HtmlResponse(url=spider.bro.current_url,body=page_text,encoding='utf-8',request=request)
setting.py
开启中间件
DOWNLOADER_MIDDLEWARES = { 'wangyipro.middlewares.WangyiproDownloaderMiddleware': 543, }