这篇将爬虫框架scrapy篇三中的第四步展开来讲,主要讲数据存入mongodb和mysql的不同方法
目录
1、数据存入mongodb,连接数据库的两种方法
1.1 连接方式一:直接初始化,传入相应的值
1.2 连接方式二: 在setting.py配置文件中设置参数,调用setting.py文件中的参数值
2、数据存入mysql,插入数据的两种方式
2.1 插入方式一:同步插入数据
2.2 插入方式二:异步插入数据(连接池)
1、数据存入mongodb,连接数据库的两种方法
链接MongoDB数据库有两种方法:
1、不需要在setting.py配置相应的参数,直接初始化连接参数
2、需要在setting.py配置相应的参数
1.1 连接方式一:直接初始化,传入相应的值
pipelines
from pymongo import MongoClient
from scrapy.exceptions import DropItem
# 存入mongodb数据库,初始化的时候,直接传入相应的值
class Movie80SPipeline:
def __init__(self, databaseIp='127.0.0.1', databasePort=27017,
mongodbName='scrapy_movie80'):
client = MongoClient(databaseIp, databasePort)
self.db = client[mongodbName]
# self.db.authenticate(user, password)
self.title = set() # 定义数据去重的集合
def process_item(self, item, spider):
title = item['moviename'] # 取出要进行判断数据是否重复的字段
if title in self.title: # 如果存在集合中则直接删除该项,
raise DropItem('{}已存在'.format(title))
else:
self.title.add(title) # 如果数据不重复,则加入集合
postItem = dict(item) # 把item转化成字典形式
self.db.scrapy.insert(postItem) # 向数据库插入一条记录
# 优先级高的管道类这里必须返回item,否则在优先级低的管道类中接收不到item会报错
return item
1.2 连接方式二: 在setting.py配置文件中设置参数,调用setting.py文件中的参数值
settings
# 在settings中加上以下参数
MONGO_HOST = "127.0.0.1" # 主机IP
MONGO_PORT = 27017 # 端口号
MONGO_DB = "scrapy_movie80" # 库名
MONGO_COLL = "scrapy" # collection名,相当于表名
MONGO_USER = "" # 用户名
MONGO_PSW = "" # 用户密码
pipelines
import pymongo
from scrapy.utils.project import get_project_settings
settings = get_project_settings()
# 存入mongodb数据库,在setting.py配置文件中设置参数,调用setting.py文件中的参数值
class Movie80SPipeline:
def __init__(self):
# 链接数据库
client = pymongo.MongoClient(host=settings['MONGO_HOST'], port=settings['MONGO_PORT'])
self.db = client[settings['MONGO_DB']] # 获得数据库的句柄
self.coll = self.db[settings['MONGO_COLL']] # 获得collection的句柄
# 数据库登录需要帐号密码的话
# self.db.authenticate(settings['MONGO_USER'], settings['MONGO_PSW'])
self.title = set() # 定义数据去重的集合
def process_item(self, item, spider):
title = item['moviename'] # 取出要进行判断数据是否重复的字段
if title in self.title: # 如果存在集合中则直接删除该项,
raise DropItem('{}已存在'.format(title))
else:
self.title.add(title) # 如果数据不重复,则加入集合
postItem = dict(item) # 把item转化成字典形式
self.db.scrapy.insert(postItem) # 向数据库插入一条记录
# 优先级高的管道类这里必须返回item,否则在优先级低的管道类中接收不到item会报错
return item
2、数据存入mysql,插入数据的两种方式
链接mysql的方式和mongodb一样也是两种,大同小异,不做细讲。
主要讲讲mysql的存入方式:
同步插入(一个连接,适用数据量小的情况)
同步插入数据就是一条数据一条数据的插入数据库,当数据量特别大的时候,就需要排队等待。所以,在数据量大的情况下,同步插入就会显得速度很慢。
异步插入(连接池,多个连接,适用数据量大的情况)。
异步插入是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。在数据量大的时候,多个连接对数据进行操作,大大提升了插入数据的效率。
2.1 插入方式一:同步插入数据
pipelines
import pymysql
# 存入mysql数据库
class Movie80SPipeline:
"""
同步操作
"""
def __init__(self):
# 建立连接
self.conn = pymysql.connect(host='127.0.0.1', port=3306, db="scrapy_movie80", user='root', passwd='123456', charset='utf8')
# 创建游标
self.cursor = self.conn.cursor()
# 定义数据去重的集合
self.title = set()
def process_item(self, item, spider):
title = item['moviename'] # 取出要进行判断数据是否重复的字段
if title in self.title: # 如果存在集合中则直接删除该项,
raise DropItem('{}已存在'.format(title))
else:
self.title.add(title) # 如果数据不重复,则加入集合
# sql语句
insert_sql = """
insert into scrapy(moviename,movielink,moviedirector,movieregion,movieReleasedate) VALUES(%s,%s,%s,%s,%s)
"""
try:
# 执行插入数据到数据库操作
self.cursor.execute(insert_sql,
(item['moviename'], item['movielink'], item['moviedirector'], item['movieregion'],
item['movieReleasedate']))
# 提交,不进行提交无法保存到数据库
self.conn.commit()
except:
# 保存数据失败,回滚操作
self.conn.rollback()
# 优先级高的管道类这里必须返回item,否则在优先级低的管道类中接收不到item会报错
return item
def close_spider(self, spider):
# 关闭游标和连接
self.cursor.close()
self.conn.close()
2.2 插入方式二:异步插入数据(连接池)
settings
# Mysql数据库的配置信息
MYSQL_HOST = '127.0.0.1' # 主机IP
MYSQL_PORT = 3306 # 数据库端口
MYSQL_DBNAME = 'scrapy_movie80' # 数据库名字
MYSQL_USER = 'root' # 数据库账号
MYSQL_PASSWD = 'xxx' # 数据库密码
pipelines
import pymysql
from twisted.enterprise import adbapi
# # 存入mysql数据库
class Movie80SPipeline1(object):
# """
# 异步操作,连接池
# """
def __init__(self, dbpool):
self.dbpool = dbpool
# 定义数据去重的集合
self.title = set()
@classmethod
def from_settings(cls, settings): # 函数名固定,会被scrapy调用,直接可用settings的值
"""
数据库建立连接
:param settings: 配置参数
:return: 实例化参数
"""
adbparams = dict(
host=settings['MYSQL_HOST'],
db=settings['MYSQL_DBNAME'],
user=settings['MYSQL_USER'],
password=settings['MYSQL_PASSWD'],
cursorclass=pymysql.cursors.DictCursor # 指定cursor类型
)
# 连接数据池ConnectionPool,使用pymysql连接
dbpool = adbapi.ConnectionPool('pymysql', **adbparams)
# 返回实例化参数
return cls(dbpool)
def process_item(self, item, spider):
"""
使用twisted将MySQL插入变成异步执行。通过连接池执行具体的sql操作,返回一个对象
"""
query = self.dbpool.runInteraction(self.do_insert, item) # 指定操作方法和操作数据
# 添加异常处理
query.addCallback(self.handle_error) # 处理异常
# 优先级最低的管道类的return会在控制台输出原item数据,可以选择不写
return item
def do_insert(self, cursor, item):
# 对数据库进行插入操作,并不需要commit,twisted会自动commit
insert_sql = """
insert into scrapy(moviename,movielink,moviedirector,movieregion,movieReleasedate) VALUES(%s,%s,%s,%s,%s)
"""
cursor.execute(insert_sql, (item['moviename'], item['movielink'],
item['moviedirector'], item['movieregion'], item['movieReleasedate']))
def handle_error(self, failure):
if failure:
# 打印错误信息
print(failure)
传送门
爬虫框架scrapy篇一——scrapy的架构
https://www.jianshu.com/p/39b326f9cad6
爬虫框架scrapy篇二——创建一个scrapy项目
https://www.jianshu.com/p/00d99a9628b0
爬虫框架scrapy篇三——数据的处理与持久化以及遇到的一些问题
https://www.jianshu.com/p/8824623b551c
爬虫框架scrapy篇五——其他操作:post翻页请求
https://www.jianshu.com/p/bca689b4ebbd
参考:
MySql数据库连接池
scrapy保存到mysql数据库
Python:No module named 'scrapy.conf'