|
大数据时代,各行各业对数据采集的需求日益增多,网络爬虫的运用也更为广泛,越来越多的人开始学习网络爬虫这项技术,K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章,为实现从易到难全方位覆盖,特设【0基础学爬虫】专栏,帮助小白快速入门爬虫,本期为数据存储。
概述
上期我们介绍到了文件存储,讲到了如何将数据存入各种文本文件之中,这种数据存储方式虽然很简便,但是存在很多问题,如:数据容易丢失、文件容易损坏、数据不易共享。因此本期将介绍更加实用的数据库存储方式。
本文将介绍三种流行的数据存储技术:
MySQL:一种关系型数据库管理系统,广泛用于企业级应用程序中
MongoDB:一种文档型数据库,适合处理半结构化数据和大规模数据集。
Redis:一种内存数据库,用于处理高速读写操作和缓存数据。
在本文中,我们将分别介绍 MySQL、MongoDB 和 Redis 的优缺点、适用场景以及如何选择最适合自己的数据库存储技术。作为爬虫初学者,本文将帮助你更好地理解这三种数据库存储技术的工作原理,以及如何选择适合你的应用程序的数据库。
MySQL
介绍
MySQL 是一种开源的关系型数据库管理系统,是目前最流行的关系型数据库之一。MySQL 是一个快速、高效的数据库系统,能够处理大量的数据和请求。另一个优点是它的灵活性和可扩展性,可以根据需要进行配置和调整,以满足不同应用的需求。MySQ L使用SQL(结构化查询语言)作为其查询和管理语言,SQL 是一种标准的关系型数据库语言,用于定义、操作和查询数据。
MySQL 被广泛用于 Web 开发、数据分析和数据存储等领域,是一个非常强大和受欢迎的数据库系统。同时,由于它是开源软件,因此可以在不支付任何费用的情况下使用和修改,这也使得它成为了很多开发者的首选数据库系统。
安装
首先需要安装 MySQL 数据库,在MySQL官网下载对应版本的文件进行安装。
安装好 MySQL 并确保 MySQL 能够正常运行后需要安装 Python 的第三方库 PyMySQL。
pip install pymysql
使用
在使用 Python 操作 MySQL 数据库前,我们需要先了解一下基本的 sql 语句。
sql 语句
SQL 即结构化查询语言 (Structured Query Language),是一种特殊目的的编程语言,是一种数据库查询和程序设计语言。
数据库操作- -- 创建数据库
- create database 数据库库名;
- -- 查看所有数据库
- show databases;
- -- 使用数据库
- use 数据库库名;
- -- 删除数据库
- drop database 数据库库名;
复制代码 表操作- -- 创建表
- create table 表名(
- 属性名 数据类型 约束,
- .
- .
- );
- -- 查看表结构
- desc 表名;
- -- 修改表名
- alter table 表名 rename to 新的表名;
- -- 添加新字段
- alter table 表名 add 属性;数据类型;约束;
- -- 删除一个字段
- alter table 表名 drop 属性名;
- -- 删除表
- drop table 表名;
复制代码 约束描述PRIMARY KEY主键约束。第一范式要求每一张表都应该有一个主键作为表的唯一标识,主键具有唯一性。UNIQUE唯一约束。标识该属性的值是唯一的。NOT NULL非空约束。标识该属性的值不能为空。FOREIGN KEY外键约束。 标识该属性为该表的外键,与某表的主键关联。AUTO_INCREMENT标识该属性的值自动增加DEFAULT为该属性设置默认值插入数据- insert into 表名(属性1, 属性2, 属性3) values(值1,值2,值3);
复制代码 修改数据- -- 修改指定数据
- update 表名 set 属性1 = 值1, 属性2 = 值2 where 条件表达式;
复制代码 删除数据- -- 删除表中所有数据
- delete from 表名;
- -- 删除指定数据
- delete from 表名 where 条件表达式;
复制代码 查询数据- -- 查询所有数据
- select * from 表名;
- -- 条件查询
- select 字段1,字段2 from 表名 where 字段 in (值1,值2,值3...)
- -- 多条件查询
- select 字段1,字段2 from 表名 where 字段1 in (值1,值2,值3...) and 字段2 in (值4,值5,值6...)
- -- 范围查询
- select 字段1,字段2 from 表名 where 字段 BETWEEN 值1 and 值2; -- 查询字段值在值1到值2之间的记录
- -- 模糊查询
- -- % 代表任意字符;
- -- _ 代表单个字符;
- select * from 表名 where 字段 like '张%'; -- 查询字段值以张开头的记录
- select * from 表名 where 字段 like '_张%'; -- 查询字段值第二位是张的记录
- -- 排序
- select 字段 from 表名 order by 字段名 ASC|DESC; -- ASC升序 DESC降序
- -- 去重
- select DISTINCT 字段 from 表名;
- -- 分组查询
- select 字段1,AVG(字段2) from 表名 group by 字段1; -- 按字段1分组,查询字段2的平均值
- -- 示例
- select gender,avg(grade) from users group by gender; -- 按性别分组,查询各性别的平均成绩
复制代码 Python 操作 MySQL
连接数据库- import pymysql
- db = pymysql.connect(
- host='localhost',
- user='root',
- database='user',
- password='test123',
- port=3306,
- charset='utf8mb4'
- )
- #获取操作游标
- cursor = db.cursor()
复制代码host:IP地址
user:用户名
password:密码
database:库名
port:数据库端口
charset:字符集编码
连接数据库后,调用 cursor() 方法获取对数据库的操作游标,通过游标可以执行 sql 语句。
创建表- #sql 语句
- sql = 'CREATE TABLE students (id VARCHAR(255) PRIMARY KEY, name VARCHAR(255) NOT NULL, age INT NOT NULL, grade INT)'
- # 通过游标执行 sql 语句
- cursor.execute(sql)
- #关闭数据库连接
- db.close()
复制代码 插入数据
上一步中我们创建了一张 students 表,现在我们要向 students 表中插入数据。- #插入语句
- sql = 'INSERT INTO students(id, name, age, grade) values ("%(id)s", "%(name)s", %(age)d, %(grade)d)'
- try:
- #执行语句
- cursor.execute(sql % {'id': '1001', 'name': '张三', 'age': 25, 'grade': 92})
- #提交
- db.commit()
- except:
- #插入异常则回滚数据
- print('插入异常')
- db.rollback()
- db.close()
复制代码 插入数据时,字符串类型的数据应被单引号或双引号包裹,否则会导致程序异常。在执行语句和提交语句时应该进行异常处理,发生异常时回滚数据,确保事务的原子性。
更新数据- sql = 'UPDATE students SET grade = %(grade)d WHERE id = "%(id)s"'
- try:
- cursor.execute(sql % {'id':'1001', 'grade': 90})
- db.commit()
- except:
- db.rollback()
- db.close()
复制代码 删除数据- sql = 'DELETE FROM students WHERE id = "%(id)s"'
- try:
- cursor.execute(sql % {'id':'1001'})
- db.commit()
- except:
- db.rollback()
- db.close()
复制代码 查询数据
在查询数据之前,我们可以重新创建一个新的表,插入一些数据来作为案例。- # 创建表
- create_table_sql = """CREATE TABLE students (
- id INT PRIMARY KEY,
- name VARCHAR(255) NOT NULL,
- age INT NOT NULL,
- gender ENUM('男', '女') DEFAULT '男' NOT NULL,
- grade INT DEFAULT NULL
- );
- """
- # 插入数据
- insert_sql = """
- INSERT INTO students (id, name, age, gender, grade)
- VALUES
- (1, '张三', 20, '男', 80),
- (2, '李四', 19, '男', 75),
- (3, '王五', 21, '男', 88),
- (4, '赵六', 18, '女', 92),
- (5, '钱七', 20, '女', 85),
- (6, '孙八', 19, '男', 78),
- (7, '周九', 21, '女', 90),
- (8, '吴十', 18, '男', 86),
- (9, '郑一', 20, '女', 81),
- (10, '王二', 19, '男', 77);
- """
复制代码 执行查询语句后,可以调用 fetchall 方法获取查询结果。- # 查询年龄大于20岁的记录
- sql = """
- SELECT * FROM students WHERE age > 20
- """
- cursor.execute(sql)
- # 返回一条查询结果
- # result = cursor.fetchall()
- # 返回所有查询结果
- result = cursor.fetchall()
- print(result)
- # ((3, '王五', 21, '男', 88), (7, '周九', 21, '女', 90))
复制代码- # 查询姓名以张开头的记录
- select_like_sql = """
- SELECT * FROM students WHERE name like '张%'
- """
- ((1, '张三', 20, '男', 80),)
- # 以性别分组查询平均分
- select_group_sql = """
- SELECT gender, avg(grade) FROM students group by gender
- """
- (('男', Decimal('80.6667')), ('女', Decimal('87.0000')))
复制代码 MongoDB
介绍
上文中讲到的 MySQL 是一种关系型数据库,而 MongoDB 与下文中的 Redis 都属于非关系型数据库,也被称为 NoSQL(Not Only SQL)。MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
安装
首先需要安装 MongoDB 数据库,在MongoDB官网下载对应版本的文件进行安装。
安装好 MongoDB 并确保 MongoDB 能够正常运行后需要安装 Python 的第三方库 PyMongo。
pip install pymongo
使用
首先需要了解一下 MongoDB 的常用命令- -- 查看当前数据库
- db
- -- 查看所有数据库
- show dbs
- -- 切换数据库(不存在则创建)
- use 数据库名
- -- 删除数据库
- db.dropDatabase()
- -- 创建集合
- db.createCollection(集合名称, 创建参数)
- -- 查看集合(与 MySQL 中的表相似)
- show tables
- show collections
- -- 删除集合
- db.集合名称.drop()
复制代码 Python 操作 MongoDB
连接数据库- import pymongo
- client = pymongo.MongoClient('mongodb://localhost:27017/')
复制代码 插入数据- # 使用test库(没有则创建)
- db = client['test']
- # 创建一个集合
- students = db['students']
- data = {'id':'1001','name':'张三','age':20,'gender':'男'}
- # 插入一条
- result_one = students.insert_one(data)
- # 插入多条
- resutl_many = students.insert_many([{'id':'1002','name':'李四','age':22,'gender':'男'},{'id':'1003','name':'王五','age':24,'gender':'女'}])
- print(result)
- print(resutl_many)
- # <pymongo.results.InsertOneResult object at 0x00000200BB19AA88>
- # <pymongo.results.InsertManyResult object at 0x00000200BB1D6E08>
复制代码 查询数据- # 查询一条name为李四的数据
- result_one = students.find_one({'name':'李四'})
- # {'_id': ObjectId('64375e380fa1b587bc84e32d'), 'id': '1002', 'name': '李四', 'age': 22, 'gender': '男'}
- # 查询多条,返回一个生成器
- result_many = students.find({'gender':'男'})
- # <pymongo.cursor.Cursor object at 0x000002527225A888>
- for result in result_many:
- print(result)
- # {'_id': ObjectId('64375e3b89cfb1bb0c54b1c3'), 'id': '1001', 'name': '张三', 'age': 20, 'gender': '男'}
- # {'_id': ObjectId('64375e3b89cfb1bb0c54b1c4'), 'id': '1002', 'name': '李四', 'age': 22, 'gender': '男'}
复制代码 比较符- # 查询年龄大于20的数据
- students.find({'age':{'$gt':20}})
- # 查询年龄不等于20的数据
- students.find({'age':{'$ne':20}})
复制代码 符号含义$lt小于$gt大于$lte小于等于$gte大于等于$ne不等于$in在范围内$nin不在范围内更新数据- query = {"name":"张三"}
- new_values = {"$set":{ "age":25 }}
- # 更新第一条符合条件的数据
- # students.update_many(query, new_values)
- # 更新所有符合条件的数据
- result = students.update_many(query, new_values)
- # <pymongo.results.UpdateResult object at 0x0000022C92BA8E08>
复制代码 删除数据- # 删除一条
- query = {"name": "张三"}
- students.delete_one(query)
- # 删除多条
- query = {"age": {"$gt":22}}
- students.delete_many(query)
- # 删除所有
- students.delete_many({})
- # 删除集合
- students.drop()
复制代码 Redis
介绍
Redis是一个基于内存的键值对存储系统,也被称为数据结构服务器,支持多种数据结构。它被广泛用于缓存、会话管理、消息队列等应用程序中。
安装
首先需要安装 Redis 数据库,安装好 Redis 并确保 Redis 能够正常运行后需要安装 Python 的第三方库 redis-py。
pip install redis
使用
Redis 基本数据类型
字符串:字符串(string)是 redis 最基本的数据类型,它可以包含任意数据。
哈希:哈希(hash)是一个键值对集合,是一个 string 类型的 field 和 value 的映射表。
列表:列表(list)是简单的字符串列表,按插入顺序排序,reids 列表支持在它的头尾部插入数据。
集合:集合(set)是字符串类型的无序集合,集合内的元素具有唯一性。
有序集合:有序集合(zset)与集合一样也是字符串类型的集合。不同的是有序集合中每个元素都会关联一个 double 类型的分数,它会通过分数来对元素进行升序排序。
Python 操作 Redis
连接数据库- from redis import StrictRedis
- redis = StrictRedis(host='localhost',port=6379,decode_responses=True)
- # Redis<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>
复制代码 字符串操作
redis 默认返回结果是字节,在连接时设置 decode_responses=True 可以将返回结果改为字符串。- # 添加一条数据,ex 为过期时间(秒),过期后键name的值就变为None
- redis.set('name','张三', ex=3)
- redis.set('nick','张三三三')
- # 返回指定键的值
- redis.get('name') # 张三
- # 设置新值,返回旧值
- redis.getset('name','李四') # 张三
- # 根据字节取值,(0,2)取前三位的字节,一个汉字三个字节,一个字母一个字节
- print(redis.getrange('nick', 0, 2)) # 张
- # 从指定位置开始修改内容
- redis.setrange('nick',3,'五五五')
- redis.get('nick') # 张五五五三
- # 批量取值
- redis.mget('name','nick') # ['李四', '张五五五']
- # 批量赋值
- redis.mset({'key1':'value1','key2':'value2'})
- redis.mget('key1', 'key2') # ['value1', 'value2']
复制代码 哈希操作- # 单个添加,向 hash1 中设置一个键值对(hash1存在则修改,不存在则创建)
- redis.hset('hash1','key1','value1')
- redis.hset('hash1','key2','value2')
- # 取hash1中所有的key
- redis.hkeys('hash1') # ['key1', 'key2']
- # 单个取hash1的key对应的值
- redis.hget('hash1', 'key1') # value1
- # 多个取hash1的key对应的值
- # 批量添加
- redis.hmset('hash2', {'key3': 'value3', 'key4': "value4"})
- # 批量取出
- redis.hmget('hash2','key3','key4') # ['value3', 'value4']
- # 取出所有键值对
- redis.hgetall('hash2') # {'key3': 'value3', 'key4': 'value4'}
- # 取出所有值
- redis.hvals('hash2') # ['value3', 'value4']
- # 取出所有键
- redis.hkeys('hash2') # ['key3', 'key4']
复制代码 列表操作- # 将元素添加到列表最左边,列表不存在则新建
- redis.lpush('grade', 88, 87, 92)
- # 将元素添加到列表最右边,列表不存在则新建
- redis.rpush('grade', 78, 67, 99)
- # 同字符串切片
- redis.lrange('grade', 0, -1) # ['92', '87', '88', '78', '67', '99']
- # 向已有列表添加数据,列表不存在不会新建
- redis.lpushx('age',22)
- # 返回列表长度
- redis.llen('age') # 0
- # 在某个值的前或后插入一个值
- # 在左边一个元素 88 前插入元素 66
- redis.linsert('grade','before',88,66)
- # 修改列表中某个位置的值
- # 将索引号为0的元素值修改为77
- redis.lset('grade', 0, 77)
- # 删除指定值
- # 删除左边第一次出现的 87
- redis.lrem('grade', 87, 1)
- # 删除所有87
- redis.lrem('grade', 87, 0)
- # 删除并返回
- redis.lpop('grade') # 删除最左边的元素并返回
复制代码 集合操作- # 添加元素
- redis.sadd('count', 88, 87, 92)
- # 集合长度
- redis.scard('count') # 3
- # 获取所有元素
- redis.smembers('count') # {'92', '87', '88'}
- # 删除随机元素并返回
- redis.spop('count') # 87
- # 删除指定元素
- redis.srem('count',88)
- # 差集,返回在集合1中且不在集合2中的元素集合
- redis.sadd('set1', 12, 13, 14, 15)
- redis.sadd('set2', 12, 15, 18, 21)
- # 在set1中且不在set2中的元素
- redis.sdiff('set1','set2') # {'13', '14'}
- # 交集,返回多个集合相同的元素集合
- redis.sinter('set1','set2') # {'15', '12'}
- # 并集,返回多个集合的并集
- redis.sunion('set1','set2') # {'13', '12', '18', '21', '14', '15'}
复制代码 有序集合操作- # 添加元素
- redis.zadd('fruit',{'apple':10,'banana':6})
- # 集合长度
- redis.zcard('fruit') # 2
- # 获取所有元素
- redis.zrange('fruit',0,-1) # ['banana', 'apple']
- # 从大到小排序
- redis.zrevrange('fruit',0,-1) # ['apple', 'banana']
- # 获取在某个区间中的元素个数
- redis.zcount('fruit', 5, 8) # 1
- # 删除指定值
- redis.zrem('fruit', 'apple')
- # 根据范围删除
- redis.zremrangebyscore('fruit', 5, 8)
- # 获取值对应的分数
- redis.zscore('fruit', 'apple') # 10.0
复制代码 总结
以上讲到了三种数据库的基本使用方法以及它们各自的特点,MySQL 使用 sql 语句来对数据进行操作,比较成熟,但是在海量数据处理时效率会显著变慢。MongoDB是一个面向集合的,模式自由的文档型数据库,采用虚拟内存与持久化的存储方式,能够存储 JSON 风格的数据,能做到数据的高速读写,但是它不支持事务操作,且占用空间过大。Redis 则是一个纯粹的内存数据库,所有数据存放在内存中,它也支持数据的持久化,可以将数据存到磁盘中,它拥有多种数据类型,性能极高,但与 MongoDB 一样不适合存储大量数据。 因此在开发时,选择哪种数据库来存储数据需要以自己的实际需求为准。
来源:https://www.cnblogs.com/ikdl/p/17314969.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|