下载中间件处于引擎和下载器之间,在发起request请求之前我们可以通过下载中间件设置一些反爬虫的措施,反爬虫措施大致分为以下几点:
基于请求头的反爬(合理构建请求头-headers)-->(请求头参数(UA、referer、cookie...)) -->常见的状态码(200:请求成功、301:永久重定向、302:临时重定向、400:客户端错误、401:未授权、403:服务器拒绝访问、404:页面未找到、405:请求方式不对、408:请求超时、500:服务器错误、503:服务器不可用)、常见的请求方式(post、get)
基于cookie的反爬(获取需要用户登录才能获取的信息)-->(可以保存一个cookie池,文件存储、数据库存储:账号密码cookie值)--> 如何获取cookie(浏览器中的请求头,)、如何验证cookie(访问需要cookie登录的网页)、怎么进行模拟登录(urllib(cookiejar)、request请求;复杂的可通过selenium))
基于ip的反爬(设置代理)(用户没登录之前对方会通过你的ip标记用户)-->(代理原理(客户端发起请求给代理服务器,代理服务器对目标服务器发送请求和接收响应,最后把结果返回客户端)(获取代理方式【快代理、西刺等网站的高匿代理】) 如何检测代理(可发起请求检测) 对方服务器客户端对ip检测比较严格的时候,可设置一个代理池)
基于动态加载的网页(ajax、js、jquery--》(selenium-无头浏览器和有头浏览器))
关于数据加密(分析js代码、如果网站的数据可以分享,我们也可以通过分享的连接获取数据)
自定义爬虫中间件:打开Middlewares.py文件
- Middlewares参考源码(最常用的几种方法)
def process_request(self,request,spider):
所有的request请求都会进过这个方法
def process_response(self,request,response,spider):
对响应结果做处理
返回:request对象、response对象、ignorerequest方法-》返回错误
def process_exception(self, response, exception, spider):
对返回的错误做一个处理
下面为大家介绍几种反爬的方法
模拟浏览器登录(UA)
Middlewares:
class UserAgentDownloadMiddlerware(object):
def process_request(self,request,spider):
"""
所有的request在交给下载器之前,都会经过这个方法
:param request:
:param spider:
:return:
"""
from fake_useragent import UserAgent
userAgent = UserAgent()
random_ua = userAgent.random
if random_ua:
print('经过了下载中间件',random_ua)
request.headers['User-Agent'] = random_ua
设置cookie中间件
Middlewares
class CookiesDownloadMiddlerware(object):
def process_request(self,request,spider):
COOKIES = spider.settings['COOKIES']
import random
cookie_rm = random.choice(COOKIES)
if cookie_rm:
request.cookie = cookie_rm
settings:
# cookie池
COOKIES = [
{'cookie1':'XXX'},
{'cookie1':'XXX'},
]
设置代理
class ProxyDownloadMiddlerware(object):
def process_request(self,request,spider):
proxies = spider.settings['PROXIES']
import random
proxy_rm = random.choice(proxies)
if proxy_rm['pwd']:
import base64
base64_pwd = base64.b64encode(proxy_rm['pwd'].encode('utf-8')).decode('utf-8')
# 对应到代理服务器的信令格式里
request.headers['Proxy-Authorization'] = 'Basic ' + base64_pwd
request.meta['proxy'] = proxy_rm['ip']
else:
request.meta['proxy'] = proxy_rm['ip']
settings:
PROXIES = [
{'ip': '61.128.208.94:3128','pwd': None},
{'ip': '122.96.59.104:80', 'pwd': '密码'},
{'ip': '122.224.249.122:8088', 'pwd': None},
]
scrapy 并不支持动态网页的爬取,我们可以通过selenium进行动态页面的访问
selenium与scrapy对接:
Middlewares
from selenium.common.exceptions import TimeoutException
from scrapy.http import HtmlResponse
class SeleniumDownloadMiddlerWare(object):
@classmethod
def from_crawler(cls, crawler):
s = cls()
# 信号量,一旦开启调用spider_opened,监控爬虫结束的信号
crawler.signals.connect(s.close, signal=signals.spider_closed)
return s
def close(self,spider):
import time
time.sleep(10)
spider.driver.close()
def process_request(self,request,spider):
if spider.name == 'text':
# 获取url
url = request.url
if url:
try:
spider.driver.get(url)
pageSource = spider.driver.page_source
if pageSource:
"""
url,status=200,headers=None,
body=b'',flags=None,request=None
"""
return HtmlResponse(
url=url,
status=200,
body=pageSource.encode('utf-8'),
request=request
)
except TimeoutException as err:
print('请求超时',url)
return HtmlResponse(
url=url,
status=408,
body=b'',
request=request
)
爬虫文件:
import scrapy
from selenium import webdriver
class TextSpider(scrapy.Spider):
name = 'text'
allowed_domains = ['baidu.com']
start_urls = ['http://www.baidu.com/']
# 创建浏览器驱动
driver = webdriver.Firefox(
executable_path='C://Users/Administrator/Desktop/llqqd/geckodriver.exe'
)
driver.set_page_load_timeout(10)
def parse(self, response):
print(response.status, response.request.headers)
最后不要忘了在settings中激活下载中间件
DOWNLOADER_MIDDLEWARES = {
'proxiesproject.middlewares.CookiesDownloadMiddlerware': 543,
'proxiesproject.middlewares.UserAgentDownloadMiddlerware':542,
'proxiesproject.middlewares.ProxyDownloadMiddlerware':542,
'proxiesproject.middlewares.SeleniumDownloadMiddlerWare':543,
}