FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [View Raw Code]   [Original HTTPS Page]

Notes/python-basic-notes/python-days/Day_61.md at master · We2one/Notes · GitHub

/ Notes Public

Latest commit

 

History

History
201 lines (139 loc) · 9.55 KB

File metadata and controls

201 lines (139 loc) · 9.55 KB

Scrapy-redis 分布式

Python 邮件监控

SMTP 简介
  • SMTP (Simple Mail Transfer Protocol : 简单邮件传输协议) : 一组用于由原地址到目的地址传送邮件的规则,由它来控制新建的中转方式

  • python 的 smtplib 提供了一种很方便的途径发送电子邮件,对 smtp 进行了简单的封装

    import smtplib
    smtpObj = smtplib.SMTP([host [, port [, local_hostname]]])
    • 参数说明
      1. host : SMTP 服务器主机,可以指定主机的 ip 地址或者域名 (可选参数)
      2. port : 如果提供了 host 需要指定 SMTP 服务使用的端口号, 一般端口号为 25
      3. local_hostname : 如果 SMTP 在本机上,可以指定服务器地址为 localhost
  • Python SMTP 使用 sendmail 方法发送邮件,语法格式:

    SMTP.sendmail(from_addr, to_addrs, msg [, mail_options, rcpt_options])
    • 参数说明
      1. from_addr : 邮件发送者地址
      2. to_addrs : 字符串列表,邮件发送地址
      3. msg : 发送消息,字符串 (表示邮件)
        • msg 格式 为 smtp 定义固定格式
          1. 标题
          2. 发信人
          3. 收件人
          4. 邮件内容
          5. 附件
邮件监控五个步骤
  • 五个步骤

    # 导入邮件包
    import smtplib
    # 创建邮件对象
    smtpobj = smtplib.SMTP()
    # 连接服务器
    smtpobj.connect()
    # 登录操作
    smtpobj.login()
    # 发送邮件
    smtpobj.sendmail()
    # 退出操作
    smtpobj.quit()
    1. 连接服务器 : smtp.connect(self, host='localhost', port=0, source_address=None)
    2. 登录操作 : smtplib.login(self, user, password, *, initial_response_ok=True)
    3. 发送邮件 : smtplib.sendmail(self, from_addr, to_addrs, msg, mail_options=(), rcpt_options=())

Redis 安装

  1. 安装步骤

    1. 将下载好的 redis 安装包解压到指定目录
    2. 将 redis 安装目录配置到环境变量的 path 中
    3. 在 cmd 中运行命令 redis-server ,查看是否可以启动 redis 数据库
  2. redis 重要文件

    • redis.windows.conf : redis 的配置文件
    • redis-cli.exe : 客户端命令程序
    • redis-server.exe : 服务端命令程序
    • 默认端口 : 6379
  3. 一个 reids 配置文件就是一个 redis 数据库

  4. 开启多个 redis 服务

    1. 复制配置文件,名称后添加需要开启的端口号

    2. 打开配置文文件更改端口号

      # Accept connections on the specified port, default is 6379 (IANA #815344).
      # If port 0 is specified Redis will not listen on a TCP socket.
      port 6379
      
    3. 开启多个命令端口,使用 redis-server [配置文件] 启动 redis 服务

    4. 链接 redis 数据库 redis-cli -p 端口号

  5. redis 优点

    1. redis 有丰富的数据结构
    2. redis 身为内存化数据库,可以持久化保存数据
  6. redis 文档

Scrapy-Redis 分布式

分布式爬虫简介
  1. 使用分布式的原因

    • 分布式爬虫就是多台计算机上都安装爬虫程序,重点是联合采集 (例如: 三台服务器上三个爬虫同时爬取一个网页,需要一个 状态管理器集中分配,去重已爬过的url)
    • 状态管理器 : 也是一个服务,需要部署在某一台服务器上,通过状态管理器集中分配需要抓取的URL 以及去重
    • 分布式爬虫的优点
      1. 充分利用多机器的带宽进行加速爬取,一台服务器上带宽有限
      2. 充分利用多机器的 IP 加速爬取的速度,一台服务器如果爬取过快容易被封 IP
    • 分布式爬虫 : 多台服务器有序的爬取任务为队列的 URL
  2. Scrapy 和 Scrapy-Redis 的区别

    1. Scrapy 是一个通用爬虫框架,不支持分布式.分布式爬取需要 Scrapy-redis.
    2. Scrapy-redis **提供以下四种组件 (components) **,使用分布式爬取时需要对四种组件进行修改
      1. Scheduler
      2. Duplication Filter
      3. Item Pipeline
      4. Base Spider
    3. 安装 Scrapy-redis : pip intsall scrapy-redis
  3. Scrapy-redis 架构

    1. Scheduler 调度器 : 负责对新的 request 进行入队操作 (加入 Scrapy queue), 取出下一个要爬取的 request (从 Scrapy queue 中取出)等操作

      • Scrapy 改造了 python 本来的 **collection.deque (双向队列) ** 形成自己的 Scrapy queue

      • Scrapy 多个 spider 不能共享待爬取队列 Scrapy queue, 即 Scrapy 本身不支持爬虫分布式,Scrapy-redis 解决就是把 Scrapy queue 换为 redis 数据库 (也是指 redis 队列),在同一个 redis-server 存放要爬取的 request,便可以让多个 spider 在一个 redis 数据库读取

      • Scrapy-redis 把待爬取的队列按照优先级建立了一个字典结构,然后根据优先级,决定队列顺序,出列时优先级较小的优先出列.

        {
        	优先级0 : 队列0,
        	优先级1 : 队列1,
        	优先级2 : 队列2,
        	...
        }
        
    2. Duplication Filter (DupeFilter) : 负责 Scrapy-redis 的去重功能,通过redis 的 set 不重复 的特性,实现去重.

      • Scrapy 去重 : 用集合实现 request 去重,Scrapy 将已将发送的 request 指纹放入一个集合中,把下一个 request 指纹拿到集合中对比,如果指纹存在于集合,说明 request 发送过了,没有则继续操作

        def request_seen(self, request):
            # self.request_fingerprints(request) 一个指纹集合
            fp = self.request_fingerprints(request)
            # 核心操作
            if fp in self.fingerprints:
                return True
            self.fingerprints.add(fp)
            if self.file:
                self.file.write(fp + os.linesep)
      • Scrapy-redis 去重 : 调度器从引擎接受 request , 将 request 的指纹存入 redis 的 set 检查是否出现了重复,并将不重复的 request push 写入 redis 的 request queue

      • Scrapy-redis 请求过程 : 引擎请求 request (Spider 发送出的) 时,调度器从 redis 的 request queue 队列里根据优先级 pop 出一个 request 给引擎,引擎将此 request 发送给 spider 处理

    3. Item Pipeline

      • Scrapy-redis 存储过程 : 引擎将 (spider 返回的) 爬取到的 Item 发送给 spider 处理; Item Pipeline 将爬取到的 Item 存入 redis 的 Items queue

      • 修改过后的 Item Pipeline 可以很方便的 根据 key 从 item queue 提取 item,从而实现 items processes 集群

    4. Base Spider : 重写后的 RedisSpider 继承了 Spider 和 **RedisMixin (从 redis 中读取 url) ** 两个类

      • 当生成一个 Spider 继承 RedisSpider 时, 调用 setup_redis 函数,这个函数连接 redis 数据库,然后会设置 signals (信号):
        1. spider 空闲的时候的 signals : 会调用 spider_idle 函数,这个函数调用 schedule_next_request 函数,保证 spider 一直存活,并且抛出 DontCloseSpider 异常
        2. 抓取到 item 时的 signals : 调用 item-scraped 函数,这个函数会调用 schedule_next_request 函数,获取下一个 request
  4. 总结

    1. 重写 schedule (调度器)spider 类 : 实现调度spider 启动redis 的交互
    2. 实现新的 dupefilter 类queue 类 : 达到 判重调度容器redis 交互,由于每个主机上的爬虫都会访问同一个 redis 数据库,所以调度和判重都统一管理,达到分布式的目的
    3. spider 初始化时会同时初始化一个对应的 scheduler 对象, 这个调度器对象通过读取 settings,配置好自己的调度容器 queue判重工具 dupefilter
    4. Scrapy-redis 开始爬取 : 每当一个 spider 产出一个 request 的时候,Scrapy 引擎会把这个 request 递交给这个 spider 对应的 scheduler 对象进行调度, scheduler 对象通过访问 redis 对 request 进行判重,如果不重复就把其添加到 redis 中的调度器队列里. 当调度条件满足时, scheduler 对象就从 redis 的调度器队列取出一个 request 发送给 spider ,让它爬取
    5. **Scrapy-redis 爬取结束之后 ** : spider 爬取了所有暂时可用的 url 之后, scheduler 发现这个 spider 对应的 redis 的调度器队列空了,于是触发信号 spider_idle, spider 收到这个信号之后,直接连接 redis 读取 start_urls 池,拿到新一批 url, 重复 工作

增量爬虫

增量爬虫
  • 增量爬虫 : 通过爬虫程序监控某网站的数据更新情况,以便可以爬取到该网站更新出的新数据
  • 增量爬取步骤 (核心 : 去重, 可以在1、2步随机一个去重)
    1. 在发送请求前判断该 URL 是否爬取过 (去重 : 适合不断有新网页出现的网站: 小说网、每日新闻)
    2. 解析内容后判断这部分内容是否爬取过 (去重 : 适合页面内容会更新的网站)
    3. 写入存储介质时判断内容是否在介质中
  • 去重方法 :
    • 将爬取过程中产生的 url 进行存储,存储在 redis 的 set 中,当下次进行数据爬取时,首先判断即将发起请求的 url 是否存储在 url 的 set 中存在,如果不存在则请求
    • 对爬取到的网页进行唯一标识限定,然后将该唯一标识限定存储至 redis 的 set 中,当下次爬取到网页数据时,在持久化存储时,首先判断该数据唯一标识符在 redis 中的 set 中是否存在,进一步决定是否进行持久化存储

Back | FazBrowse Home | New Git URL