Scrapy下载中间件

下载中间件处于引擎和下载器之间,在发起request请求之前我们可以通过下载中间件设置一些反爬虫的措施,反爬虫措施大致分为以下几点:

  1. 基于请求头的反爬(合理构建请求头-headers)-->(请求头参数(UA、referer、cookie...)) -->常见的状态码(200:请求成功、301:永久重定向、302:临时重定向、400:客户端错误、401:未授权、403:服务器拒绝访问、404:页面未找到、405:请求方式不对、408:请求超时、500:服务器错误、503:服务器不可用)、常见的请求方式(post、get)

  2. 基于cookie的反爬(获取需要用户登录才能获取的信息)-->(可以保存一个cookie池,文件存储、数据库存储:账号密码cookie值)--> 如何获取cookie(浏览器中的请求头,)、如何验证cookie(访问需要cookie登录的网页)、怎么进行模拟登录(urllib(cookiejar)、request请求;复杂的可通过selenium))

  3. 基于ip的反爬(设置代理)(用户没登录之前对方会通过你的ip标记用户)-->(代理原理(客户端发起请求给代理服务器,代理服务器对目标服务器发送请求和接收响应,最后把结果返回客户端)(获取代理方式【快代理、西刺等网站的高匿代理】) 如何检测代理(可发起请求检测) 对方服务器客户端对ip检测比较严格的时候,可设置一个代理池)

  4. 基于动态加载的网页(ajax、js、jquery--》(selenium-无头浏览器和有头浏览器))

  5. 关于数据加密(分析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,
}

你可能感兴趣的:(Scrapy下载中间件)