# python爬虫分布式 **Repository Path**: shimufeng/python_crawler_distributed ## Basic Information - **Project Name**: python爬虫分布式 - **Description**: No description available - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-12-27 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 简述 ## 为什么使用分布式爬虫 ### 我们平常使用scrapy框架进行爬虫时是使用的单机爬虫,意思也就是在本机一台机器上运行,分布式爬虫是实现多台机器共同完成一个爬虫,这样可以大大提高爬虫速度实现分布式爬虫 ## 前提要领 ### 在这里我们根据自己的思想来完成分布式,毕竟思想是灵活多变的 ,一样会使用redis数据库 为什么使用redis数据库 ## redis简单介绍 ### redis数据库优点: #### 1.支持多种数据类型 #### 2.久化存储 #### 3.丰富的特性 pub/sub,key过期策略,事务,支持多个DB等 #### 4.由于是全内存操作 性能很好 ### redis数据库有五种数据类型 #### 1.string字符串 #### 2.list列表 #### 3.set集合 无序收集器 ,与列表不同的是 列表可以存储多个相同的字符串 而集合保证自己存储的都是各不相同的 #### 4.hash无序散列表 键值对 ,可以存储多个键值对之间的映射 #### 5.zset有序集合,也是用来存储键值对 有序集合的键被称为成员(member) 每个成员都是不相同的 值被称为分值(score) # 注意事项 ## 配置服务器主从 这里我们使用两台机器来简单实现一下 一台为master端一台为worker端 ### master端开启redis服务 开启之后redis是可以后台运行的进程 还需master端要做的是运行一个爬虫脚本,是为了爬取要worker端爬虫要爬取的url(如果机器多的话,master端可以只用来做redis服务) ### redis远程连接 #### 找到配置文件redis.windows.conf #### 要注销第61行 #127.0.0.1 -->允许远程连接 #### 80行修改 protected-mode no -->保护模式为否 #### 219行修改stop-writes-on-bgsave-error 改为no -->解决不能持久化问题 ### worker端要做的是连接master端开启的redis服务,从redis库里面拿出url ,然后爬取这个url的内容 # 代码流程 ## 连接redis ### redis = redis.StrictRedis(host=’’, port=6379,decode_responses=True) #### StrictRedis:Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。 简单说,官方推荐使用StrictRedis方法 #### decode_responses=True:这样写存的数据是字符串格式 ## master端配置 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1227/164005_14741465_5587202.png "master端代码.png") ### 前面说过master端只是为了爬取worker端要爬取的url ,细心的朋友会发现到日志中出现了’md5值已存在’,是因为我们在pipelines设置了MD5去重的过程,这样 ,我们的worker端就不会在爬取已经爬取过的url了 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1227/164052_d3d750dd_5587202.png "master端pipelines代码.png") ### 为什么存储redis数据库时使用hash+list #### if存储为列表时 ##### 1.master端爬取的url会存在重复的现象 ##### 2.worker端爬取url的内容后可以pop掉url(详情看worker端) ##### 3.如果使用list删除url后 ,master端可能会再次爬到worker端跑的过url,这样数据依然会有重复的数据 #### if存储为集合时 ##### 1.不会存在重复的url ,这当然是有点 ,但是依然会存在存储为列表时第三种情况 ### 所以使用hash+list的方法最合适不过了 #### 不会爬取重复的url #### pop后 ,在key为url_md5中依然存在爬取过的url转码后的MD5值 #### worker端可以充分利用时间来爬取新的url内容 ,大大节省了时间 , 提高了工作效率 ### master端跑完程序结束后 此时redis的状态 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1227/164151_f73afeaa_5587202.png "master端跑完程序结束后 此时redis的状态.png") ## worker端配置 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1227/164206_b122a6fd_5587202.png "worker端代码.png") ### scrapy代码常规写法 , 只不过url咱们就在redis中取出即可 ### 连接redis 后我用了一个无限循环的方法 当redis里面没有可以爬取的url时 退出循环 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1227/164233_d30a412d_5587202.png "worker端跑出来的数据.png") ## 看看redis数据库的情况 ![输入图片说明](https://images.gitee.com/uploads/images/2019/1227/164259_e6bbb22b_5587202.png "worker跑完程序结束后 此时redis的状态.png") ### 日志中第一行为master端爬取的url转码后的MD5值 ,尽量不要动 ,因为万一下次master端再工作时爬取之前爬过的url呢 如果要清除的话redis.delete(‘url_md5’)即可 ### 日志中第二行显示一个空列表 ,说明worker端工作完成