此博客仅为我业余记录文章所用,发布到此,仅供网友阅读参考,如有侵权,请通知我,我会删掉。
为什么要选择Redis来做分布式爬虫呢??主要的原因有两点:
1、Redis基于内存,速度快
2、Redis是非关系型数据库,Redis中集合,存储每个request的指纹
正因为Redis上述的两个特点,用redis做分布式爬虫就可以多台主机共享1个爬取队列
该项目用到:Pycharm + scrapy +Redis + Mysql,需要动手跟着操作的小伙伴可以先安装一下哦。
Redis有几种架构模式,我这里选择的是最简单的一种——单机版(即一个master、其余为slave)
既然是分布式,那就准备大于或等于2台的主机。
本次开发环境我用了4台主机。在几位小伙伴的帮忙下实现了项目,感谢他们。经测试,
耗时2分钟爬虫获取的某房产*家的数据为3000条并存入数据库。
耗时60分钟爬虫获取的某房产*家的数据为85000条并存入数据库。
耗时600分钟,暂未测试…
在这里再说一下项目实现的具体事项。
1.一台主机作为master,其他主机访问到master主机。
2.redis的指纹存放到和获取的数据保存到master主机。
!!!
所以,就有了下面这一步。
因为使用的是ubuntu系统,Mysql的权限是除本机外其他主机无法连接。
这里用的方法是创建一个新的数据库用户,用于给其他主机连接访问master的数据库。
所以需要如下操作一番,打开权限。
> 1. sudo -i
> 2. cd /etc/mysql/mysql.conf.d/
> 3. vim /mysqld.cnf
> 4. #bind-address =127.0.0.1 #仅本机连接,注释掉这句话。
> 5. exit
> 6. /etc/init/mysql/ mysql restart
> 7. mysql -uroot -p******
> 8. grant all privileges on *.* to 'sunrisecai(创建新用户)'@'%'
-identified by ‘'填写用户密码'
-with grant option;
> 9.flush privileges;
用创建的新用户登录
> 10.mysql -usunrisecai -p******
> 11.show databases;(如果看到有数据库,那创建新用户就成功了)
至此,已经可以成功访问master的数据库了。
首先!你得将代码写成scrapy的正常项目的抓取。
然后!就可以照着下面动手更改为分布式抓取了。
以下代码添加到settings.py
# settings.py
# 1.重新指定调度器: 启用Redis调度存储请求队列
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 2.重新指定去重机制: 使用scrapy_redis的去重机制。确保所有的爬虫通过Redis去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 3.不清除Redis队列: 暂停/恢复/断点续爬,True:不清除 False:清除
SCHEDULER_PERSIST = True
# 4.指定连接到redis时使用的端口和地址
## 这里需要注意,master填写localhost,,slave填写的是master的主机IP
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
# 最后千万不要忘记添加管道。
# 5.redis管道
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 200
}
以下代码添加到settings.py
## pipelines.py
import pymysql
# mysql的具体设置在settings.py,所以这里需要导入该模块
from . settings import *
class MaoyanMysqlPipeline(object):
def open_spider(self, spider):
self.db = pymysql.connect(
host=MYSQL_HOST,
user=MYSQL_USER,
password=MYSQL_PWD,
database=MYSQL_DB,
charset=MYSQL_CHAR
)
self.cursor = self.db.cursor()
def process_item(self, item, spider):
# 插入数据
ins = 'insert into 数据表名称 values(%s,%s,%s,%s)'
L = [
item['xxx'], item['xxx'], item['xxx'], item['xxx'],
]
self.cursor.execute(ins, L) # 提交操作
self.db.commit() # 写入数据库
return item
def close_spider(self,spider):
self.cursor.close() # 关闭连接
self.db.close()
## settings.py
## 在该代码最下面添加以下代码
MYSQL_HOST = 'localhost' #注:master填localhost,slave主机填写master的主机IP
MYSQL_USER = 'sunrisecai'
MYSQL_PWD = '******'
MYSQL_DB = '数据库名称'
MYSQL_CHAR = 'utf8'
## pipelines.py
import pymongo
# Mongodb具体设置在settings.py,所以这里需要导入该模块
from . settings import *
class LianjiaPipeline(object):
def process_item(self, item, spider):
return item
# mongodb存储
class MaoyanMongodbPipeline(object):
def __init__(self):
host = MONGODB_HOST,
port = MONGODB_PORT,
dbname = MONGODB_DBNAME,
sheetname = MONGODB_SHEETNAME
# 连接到Mongodb
client = pymongo.MongoClient(host, port)
db = client[dbname[0]] # 传递过来的数据是集合,不是字符串
self.post = db[sheetname]
def process_item(self, item, spider):
# 将字典文件存入 monogodb
data = dict(item)
self.post.insert(data)
return item
## settings.py
## 在该代码最下面添加以下代码
MONGODB_HOST = 'localhost' #注:master填localhost,slave主机填写master的主机IP
MONGODB_PORT = 27017
MONGODB_DBNAME = '数据库名'
MONGODB_SHEETNAME = '集合名'
至此,本项目案例就可以成功运行了。
完整项目案例代码可以留下你的邮箱,我再发送给你。
因个人能力不足,难免有错误之处,所以恳请各位指正。。