爬虫scrapy框架中间件的使用

1. scrapy中间件的分类和作用

1.1 scrapy中间件的分类

根据scrapy运行流程中所在位置不同分为:【中间件离哪个模块近就称为什么中间件】

  1. 下载中间件
  2. 爬虫中间件

1.2 scrapy中间的作用:预处理request和response对象

  1. 对header以及cookie进行更换和处理
  2. 使用代理ip等
  3. 对请求进行定制化操作,

但在scrapy默认的情况下 两种中间件都在middlewares.py一个文件中  【平时主要用下载中间件】

爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件

2. 下载中间件的使用方法:

通过下载中间件来介绍如何使用中间件: 编写一个Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启

Downloader Middlewares默认的方法:【在中间件类中,有时需要重写处理请求或者响应的方法】

  • process_request(self, request, spider):【此方法是用的最多的】

    1. 当每个request通过下载中间件时,该方法被调用。
    2. 返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法  【如果所有的下载器中间件都返回为None,则请求最终被交给下载器处理】
    3. 返回Response对象:不再请求,把response返回给引擎  【如果返回为请求,则将请求交给调度器】
    4. 返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法  【将响应对象交给spider进行解析】
  • process_response(self, request, response, spider):

    1. 当下载器完成http请求,传递响应给引擎的时候调用
    2. 返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法  【如果返回为请求,则将请求交给调度器】
    3. 返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法   【将响应对象交给spider进行解析】
  • 在settings.py中配置开启中间件,权重值越小越优先执行   【同管道的注册使用】

DOWNLOADER_MIDDLEWARES = { 'myspider.middlewares.UserAgentMiddleware': 543, }

通过豆瓣网运行爬虫观察现象

 此时示例代码:【items.py】

import scrapy


class MovieSpider(scrapy.Spider):
    name = 'movie'
    allowed_domains = ['douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        li = response.xpath('//*[@class="info"]')
        print(len(li))

启动爬虫:

scrapy crawl movie

运行效果:

 解决这个错误:

再次运行效果:

修改上面的爬虫代码,完善功能(做翻页处理):

示例代码:

import scrapy
from douban.items import DoubanItem


class MovieSpider(scrapy.Spider):
    name = 'movie'
    allowed_domains = ['douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        el_list = response.xpath('//*[@class="info"]')
        print(len(el_list))
        for el in el_list:
            item = DoubanItem()

            item['name'] = el.xpath('./div[1]/a/span[1]/text()').extract_first()
            item['score'] = el.xpath('./div[2]/div/span[2]/text()').extract_first()
            item['info'] = el.xpath('./div[2]/p[1]/text()').extract_first()
            item['desc'] = el.xpath('./div[2]/p[2]/span/text()').extract_first()
            print(item)

        #  找到后页的链接
        url = response.xpath("//span[@class='next']/a/@href").extract_first()
        #  找到最后一页没有后页链接的中止条件
        if url != None:
            url = response.urljoin(url)
            yield scrapy.Request(
                url=url
            )

运行效果:

3. 实现随机User-Agent的下载中间件

3.1 在middlewares.py中完善代码

import random
from Tencent.settings import USER_AGENTS_LIST # 注意导入路径,请忽视pycharm的错误提示

class UserAgentMiddleware(object):
    def process_request(self, request, spider):
        user_agent = random.choice(USER_AGENTS_LIST)
        request.headers['User-Agent'] = user_agent
        # 不写return

class CheckUA:
    def process_response(self,request,response,spider):
        print(request.headers['User-Agent'])
        return response # 不能少!

3.2 在settings中设置开启自定义的下载中间件,设置方法同管道

DOWNLOADER_MIDDLEWARES = {
   'Tencent.middlewares.UserAgentMiddleware': 543, # 543是权重值
   'Tencent.middlewares.CheckUA': 600, # 先执行543权重的中间件,再执行600的中间件
}

3.3 在settings中添加UA的列表  【代理|请求头可以在网上直接百度找好多】

USER_AGENTS_LIST = [
    "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"
]

注意:在settings.py中的USER_AGENTS_LIST不是固定的,可以任意起名字,调用的文件的和它对应的上就可以!

详细思路分析:

写在setting中:

示例代码:

from scrapy import signals
import random
from douban.settings import USER_AGENTS_LIST

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter

#  定义一个中间件类
class RandomUserAgent(object):

    def process_request(self, request, spider):
        # print(request.headers['User-Agent'])
        pass

运行效果:

修改完善代码:

示例代码:

from scrapy import signals
import random
from douban.settings import USER_AGENTS_LIST

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter

#  定义一个中间件类
class RandomUserAgent(object):

    def process_request(self, request, spider):
        # print(request.headers['User-Agent'])
        ua = random.choice(USER_AGENTS_LIST)
        request.headers['User-Agent'] = ua

运行效果:

4. 代理ip的使用

4.1 思路分析

  1. 代理添加的位置:request.meta中增加proxy字段
  2. 获取一个代理ip,赋值给request.meta['proxy']
    • 代理池中随机选择代理ip
    • 代理ip的webapi发送请求获取一个代理ip

4.2 具体实现

免费代理ip:  【在网上直接找免费的代理IP】

class ProxyMiddleware(object):
    def process_request(self,request,spider):
        # proxies可以在settings.py中,也可以来源于代理ip的webapi
        # proxy = random.choice(proxies) 

        # 免费的会失效,报 111 connection refused 信息!重找一个代理ip再试
        proxy = 'https://1.71.188.37:3128' 

        request.meta['proxy'] = proxy
        return None # 可以不写return

收费代理ip:

# 人民币玩家的代码(使用abuyun提供的代理ip)
import base64

# 代理隧道验证信息  这个是在那个网站上申请的
proxyServer = 'http://proxy.abuyun.com:9010' # 收费的代理ip服务器地址,这里是abuyun
proxyUser = 用户名
proxyPass = 密码
proxyAuth = "Basic " + base64.b64encode(proxyUser + ":" + proxyPass)

class ProxyMiddleware(object):
    def process_request(self, request, spider):
        # 设置代理
        request.meta["proxy"] = proxyServer
        # 设置认证
        request.headers["Proxy-Authorization"] = proxyAuth

4.3 检测代理ip是否可用

        在使用了代理ip的情况下可以在下载中间件的process_response()方法中处理代理ip的使用情况,如果该代理ip不能使用可以替换其他代理ip

class ProxyMiddleware(object):
    ......
    def process_response(self, request, response, spider):
        if response.status != '200':
            request.dont_filter = True # 重新发送的请求对象能够再次进入队列
            return requst

在settings.py中开启该中间件

示例代码:

from scrapy import signals
import random
from douban.settings import USER_AGENTS_LIST, PROXY_LIST
import base64
class RandomProxy(object):

    def process_request(self, request, spider):
        proxy = random.choice(PROXY_LIST)
        print(proxy)

        if 'user_passed' in proxy:
            #  对账号密码进行编码
            b64_up = base64.b64encode(proxy['user_passwd']).encode()
            #  设置认证
            request.headers['Proxy-Authorization'] = 'Basic ' + b64_up.decode()
            #  设置代理
            request.meta['proxy'] = proxy['ip_port']
        else:
            request.meta['proxy'] = proxy['ip_port']

运行查看效果:

 运行结果:

5. 在中间件中使用selenium

以github登陆为例

5.1 完成爬虫代码

import scrapy

class Login4Spider(scrapy.Spider):
    name = 'login'
    allowed_domains = ['github.com']
    start_urls = ['https://github.com/xxxxxxx'] # 直接对验证的url发送请求

    def parse(self, response):
        with open('check.html', 'w') as f:
            f.write(response.body.decode())

5.2 在middlewares.py中使用selenium

import time
from selenium import webdriver


def getCookies():
    # 使用selenium模拟登陆,获取并返回cookie
    username = input('输入github账号:')
    password = input('输入github密码:')
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    driver = webdriver.Chrome('/home/worker/Desktop/driver/chromedriver',
                              chrome_options=options)
    driver.get('https://github.com/login')
    time.sleep(1)
    driver.find_element_by_xpath('//*[@id="login_field"]').send_keys(username)
    time.sleep(1)
    driver.find_element_by_xpath('//*[@id="password"]').send_keys(password)
    time.sleep(1)
    driver.find_element_by_xpath('//*[@id="login"]/form/div[3]/input[3]').click()
    time.sleep(2)
    cookies_dict = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()}
    driver.quit()
    return cookies_dict

class LoginDownloaderMiddleware(object):

    def process_request(self, request, spider):
        cookies_dict = getCookies()
        print(cookies_dict)
        request.cookies = cookies_dict # 对请求对象的cookies属性进行替换

配置文件中设置开启该中间件后,运行爬虫可以在日志信息中看到selenium相关内容

示例代码:【middlewares.py】

import time
from selenium import webdriver
from scrapy.http import HtmlResponse


class SeleniumMiddleware(object):

    def process_request(self, request, spider):
        #  要对爬取的网页的几个url做个对比
        url = request.url

        if 'daydata' in url:  # 启动selenium的中间件代码是比较固定的,也就是修改一下其中的过滤条件就好
            #  也可以使用无头浏览器,为了看到效果这儿使用有头浏览器
            driver = webdriver.Chrome()

            driver.get(url)
            time.sleep(3)
            data = driver.page_source

            driver.close()

            #  创建响应对象
            res = HtmlResponse(url=url, body=data, encoding='utf-8', request=request)

            return res

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: Scrapy是一个Python爬虫框架,它提供了一种快速、高效、可扩展的方式来爬取网站数据。Scrapy的主要特点包括: 1. 基于Twisted异步网络框架,可以高效地处理大量的并发请求。 2. 支持多种数据格式,包括XML、JSON、CSV等。 3. 提供了强大的数据提取功能,可以通过XPath或CSS选择器来提取网页中的数据。 4. 支持分布式爬取,可以通过Scrapy-Redis等插件实现。 5. 提供了丰富的中间件和扩展机制,可以方便地定制爬虫行为。 Scrapy使用流程一般包括以下几个步骤: 1. 定义Item:定义需要爬取的数据结构。 2. 编写Spider:编写爬虫代码,定义如何爬取网站数据。 3. 定义Pipeline:定义数据处理流程,对爬取到的数据进行处理和存储。 4. 配置Settings:配置爬虫的一些参数,如请求头、下载延迟等。 5. 运行爬虫使用命令行工具或Scrapy API启动爬虫。 总之,Scrapy是一个功能强大、易于使用的Python爬虫框架,可以帮助开发者快速地构建高效、可扩展的爬虫应用。 ### 回答2: Scrapy是一个基于Python的开源网络爬虫框架。它可以在一个爬虫工程师的控制下自动执行爬取任务,不仅可方便地快速抓取各类网站数据,而且还能够轻松地对爬取到的数据进行处理、存储和展示。 Scrapy的功能包括了爬虫组件、下载器、中间件框架、优化器和调度器。其中,爬虫组件是Scrapy的核心模块,它负责实现对爬取网站的访问和数据解析,并抽象成Scrapy的Item类型。下载器用于获取相应网页的HTTP数据,中间件框架可以进行层层拦截和处理各种网络请求,以支持一些高级事务。另外,优化器和调度器则主要负责控制整个爬虫工程师的流程和顺序。 Scrapy使用方式极为简单。在使用Scrapy之前,首先需要使用命令“scrapy startproject”来创建一个工程,然后可在该工程下进一步创建一到多个爬虫组件并指定需要爬取的网址。接下来,我们可定义一个Item类型,来解决需要爬取的数据对象的问题。在爬虫组件中,我们需要定义如何爬取和解析数据。同时,如果希望实现登录功能,我们可在中间件框架中进行相应设置。而对于数据存储和展示等操作,我们也可以在Item Pipeline中定义。 总结起来,Scrapy框架解决了网页数据爬取的问题,提供了简单易用的API以及丰富的库,可以完成高效而优质的爬取,而且功能上也足以满足个人爬虫开发的需求。如果我们希望进一步学习更多Scrapy的应用,我们可以参考Scrapy官方文档、StackOverflow和GitHub的相关资源,以及优秀的一些自媒体博文和经验分享。 ### 回答3: Scrapy是一个Python编写的用于Web数据采集的高级抓取框架。它是一个基于Twisted框架的异步网络库,可以更高效地处理网页的并发请求和响应。Scrapy框架的架构模式和流程非常清晰,包括了一系列数据处理工具和插件,方便用户进行数据的爬取、处理、存储和展示。 Scrapy框架主要包括以下几个模块: 1. Engine: 引擎控制所有模块进行协作,调度模块接收引擎发来的请求,并将其转发给下载器,同时将下载器获得的响应反馈给引擎。 2. Scheduler: 调度器负责接收并存储引擎发来的请求,并按照一定的策略进行调度,将请求发送给下载器。 3. Downloader: 下载器负责请求网络数据,将响应返回给引擎。 4. Spider: 爬虫负责解析、处理响应,并产生需要的请求数据,将其发给引擎。爬虫是用户自定义的模块,用于指定如何对网站进行数据抓取和处理。 5. Item Pipeline: 项目管道用于处理从Spider中获取到的Item,可以对Item进行过滤、验证、清洗和存储等操作。 6. Middlewares: 中间件用于修改在引擎和下载器之间传递的请求和响应,可以被用于添加请求头、代理、IP池、处理Cookie等操作。 使用Scrapy,可以很好地解决数据采集过程中遇到的各种问题,如并发请求、防反爬虫、分布式爬取、自动重试、日志管理等。同时,Scrapy还提供了强大的数据处理工具,如XPath和CSS选择器,能够使得用户更加轻松地解析网页并提取所需要的信息。因此,Scrapy在反爬虫、数据采集等领域具有广泛的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值