第 15 章 数据存储
获取到的信息,我们通常使用文件、数据库的形式存储起来,以便再次利用。
使用文件的方式保存数据,用法比较简单,而数据库的方式则分为使用关系型数据库和非关系型数据库,其各自的代表数据库产品是MySQL和MongoDB,皆为开源产品,从性能和安全性角度都具有很强的竞争力。因而,下面介绍这两个数据库在Python中的使用。
15.1 MySQL的存储
成功从页面获取信息后,我们可以将其保存到文件中,也可以存储到数据库中。显然,使用数据库拥有更多后续分析的便利,我们采用常见的关系型数据库MySQL作为信息的保存方式。
15.1.1 安装PyMySQL和MySQL
使用Homebrew和pip工具分别安装MySQL和PyMySQL。
15.1.2 连接数据库
对数据库的使用和其它语言是一致的,无非就是连接数据库,发送指令,接收结果。
使用pymysql的connect()
方法,设置必要的信息,可以连接到MySQL数据库。
还可以直接连接到MySQL中已经存在的库:
15.1.3 对数据库进行操作
连接到数据库后,可以使用游标cursor()方法对数据库进行各种操作。
15.1.3.1 创建数据库
使用SQL语句,就可以创建数据库,创建数据库的语句如下:
import pymysql
db = pymysql.connect(host='localhost', user='root',
password='mysql', port=3306)
cursor = db.cursor()
sql = "CREATE DATABASE spiders DEFAULT CHARACTER SET utf8"
cursor.execute(sql)
db.commit()
db.close()
使用游标方法cursor()
创建游标对象,用execute()
方法执行SQL语句,再使用commit()
提交,最后使用close()
方法关闭数据库连接。
15.1.3.2 创建数据表
使用SQL语句可以创建数据表,当然前提是连接到数据库。
# coding=utf-8
import pymysql
db = pymysql.connect(host='localhost', user='root',
password='mysql', db='spiders')
cursor = db.cursor()
sql = "CREATE TABLE IF NOT EXISTS students (id VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, age INT NOT NULL, PRIMARY KEY (id))"
cursor.execute(sql)
db.commit()
db.close()
SQL语句的语法,可以参照MySQL参考手册,也可借助于类似phpMyadmin之类的工具进行生成和检测。
15.1.3.3 插入、更新、删除数据
使用INSERT语句,可以插入数据到数据表:
# coding=utf-8
import pymysql
db = pymysql.connect(host='localhost', user='root',
password='mysql', db='spiders')
cursor = db.cursor()
id = '2018'
user = 'yangjh'
age = 18
sql = 'INSERT INTO students(id,name,age) values(%s,%s,%s)'
try:
cursor.execute(sql, (id, user, age))
db.commit()
except:
db.rollback()
db.close()
插入、更新和删除操作都是对数据库进行更改的操作,这些操作的写法是:
使用rollback()方法可以回滚执行失败的操作,保持事务的原子性(atomicity),使用异常处理,可以方便地实现业务回滚。
15.2 MongoDB
MongoDB 是一款开源的非关系数据库管理软件,性能优异,在诸多大型项目中表现良好,是非关系型数据库的首选。
15.2.1 在macOS中的安装
MongoDB 只支持macOS 10.11及以后的产品。
15.2.1.1 使用包管理工具安装
我们使用在macOS 中的包管理工具Homebrew进行安装。
上述指令将安装MongoDB的最新发行版,并会自动安装MongoDB所需要的依赖环境。
15.2.1.2 运行前的准备
在启动MongoDB之前,需要创建MongoDB读写数据的目录,默认情况下,MongoDB会以/data/db
为默认目录。下面的命令将创建默认的/data/db
目录:
创建目录后,为给目录指定读写权限。然后使用如下命令将MongoDB加入到系统服务中,以便每次启动时都可自动启动MongoDB服务。
15.2.1.3 安装PyMongo库
启动虚拟python环境,然后通过pip安装PyMongo库:
👉 source bin/activate
(spider)
👉 pip3 install pymongo
Collecting pymongo
Downloading https://files.pythonhosted.org/packages/d7/ac/d2e324c1f9bcf653fa106785371a16b4709506a35b04948655de8b961a85/pymongo-3.7.2-cp37-cp37m-macosx_10_9_x86_64.whl (307kB)
100% |████████████████████████████████| 317kB 1.6MB/s
Installing collected packages: pymongo
Successfully installed pymongo-3.7.2
15.2.2 连接MongoDB
使用PyMongo库,可以在Python中对MongoDB进行操作,连接到数据库,使用MongoClient方法即可:
15.2.4 指定集合
MongoDB中的集合(collection),相当于MySQL等关系型数据库中的数据表(table),具体的信息,必须指定一个集合,才能进行存入、修改等操作。使用Collection对象,即可指定集合:
15.2.5 插入数据
推荐使用insert_one()
和insert_many()
方法来分别插入单条记录和多条记录。
card = {
"id": "20183210",
"name": 'yangjh',
"age": 20,
'gender': 'male'
}
result = collection.insert_one(card)
print(result)
print(result.inserted_id)
运行结果为:
insert_one()
方法返回一个对象,调用其inserted_id
属性,可以获得_id
字段的值。
还可以使用insert_many()
方法,一次插入多条记录:
15.2.6 查询数据
查询数据,使用find_one()
或find()
方法进行查询,顾名思义,find_one()
方法查询结果是单条,而find()
方法返回全部结果。
运行结果为:
<pymongo.cursor.Cursor object at 0x103afe550>
{'_id': ObjectId('5bf8b3f897c32c4128ae8f6f'), 'id': '20183210', 'name': 'yangjh', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('5bf8b81c97c32c433d302e60'), 'id': '20183210', 'name': 'yangjh', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('5bf8b81c97c32c433d302e61'), 'id': '20183211', 'name': 'yangzh', 'age': 20, 'gender': 'male'}
可以看出,查询结果为Cursor类型,是一个生成器,需要遍历才能获取其中所有的结果。
在使用find()或find_one()方法时,需要以对象的形式传入查询条件。常见的查询条件总结如下:
符号 | 含义 | 示例 |
---|---|---|
eq |
等于 | {'age':20} |
lt |
小于 | {'age':{'$lt':20}} |
gt |
大于 | {'age':{'$gt':20}} |
lte |
小于等于 | {'age':{'$lte':20}} |
gte |
大于等于 | {‘age’:{‘\(gte':20}} | | `ne` | 不等于 | {'age':{'\)ne’:20}} |
in |
在范围内 | {‘age’:{‘\(in':[20,30]}} | | `nin` | 不在范围内 | {'age':{'\)nin’:[20,30]}} |
regex |
匹配正则表达式 | {‘name’:{‘\(regex':'^yangzh'}} | | `exists` | 属性是否存在 | {'age':{'\)exists’:True}} |
type |
类型判断 | {‘age’:{‘\(type':'int'}} | | `text` | 文本查询 | {'\)text’:{‘\(search':'yang'}} | | `where` | 高级条件查询 | {'\)where’:‘python表达式’} |
15.2.7 计数
可以使用count()
方法统计查询结果的数量。
15.2.8 排序
使用sort()
方法进行排序,排序时需要传入字段名及升降序标记,如:
将以name字段为依据,按照字母升序进行排序。若要倒序,则传入pymongo.DESCENDING
。
15.2.9 偏移和限定
使用skip()
方法,可以从指定的位置获取查询结果。使用limit()
方法,可以限定返回的数量结果。
15.2.10 更新
使用update_one()
方法和update_many()
方法,可以更新符合条件的数据。
15.2.11 删除
使用delete_one()
方法和delete_many()
方法,可以删除符合条件的数据。
15.2.12 其他操作
还可以使用类似fine_one_and_delete()
的方法,对数据进行操作。