数据库存储
关系型数据库是爬虫应用的一种重要数据存储介质。这是因为关系型数据库不仅仅可以用于存储大量的数据,而且可以快速进行数据检索。这里介绍3种关系型数据库:
1.SQLite:是桌面关系型数据库
2.MySQL:是网络关系型数据库
3.MongoDB:是非关系型数据库
一.SQLite数据库
SQLite是一个开源、小巧、零配置的关系型数据库,支持多种平台,包括Windows、Mac OSX,Linux,Android、iOS等。
这是SQLite的官网
1.1DB Browser for SQLite
这是一款跨平台的SQLite数据库管理工具
网址http://sqlitebrowser.org
进入官网后,选择对应的版本下载即可
DB Browser for SQLite在操作上非常简便。
1.2用Python操作SQLite数据库
通过sqlit3模块提供的函数可以操作SQLite数据库,sqlite3是python内置的,不需要下载安装。
sqlit3模块在对数据进行增、删、改、查以及其他操作之前,
要先使用connect函数打开SQLite数据库,通过该函数的参数指定SQLite数据库的文件名。
打开数据库后,通过cursor方法获取sqlite3.Cursor对象,然后通过sqlite3.Cursor对象的execute方法执行各种SQL语句,如创建表、创建视图、删除记录、插入记录、查询记录等。如果执行的是SQL语句(SELECT语句),那么execute方法会返回sqlite3.Cursor对象,需要对该对象进行迭代,才能获取查询结果的值。
import sqlite3
import os
dbPath = 'data.sqlite'
# 只有data.sqlite文件不存在时才创建该文件
if not os.path.exists(dbPath):
# 创建SQLite数据库
conn = sqlite3.connect(dbPath)
# 获取sqlite3.Cursor对象
c = conn.cursor()
# 创建persons表
c.execute('''CREATE TABLE persons
(id INT PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
age INT NOT NULL,
address CHAR(50),
salary REAL);''')
# 修改数据库后必须调用commit方法提交才能生效
conn.commit()
# 关闭数据库连接
conn.close()
print('创建数据库成功')
conn = sqlite3.connect(dbPath)
c = conn.cursor()
# 删除persons表中的所有数据
c.execute('delete from persons')
# 下面的4条语句向persons表中插入4条记录
c.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (1, 'Paul', 32, 'California', 20000.00 )");
c.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (2, 'Allen', 25, 'Texas', 15000.00 )");
c.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (3, 'Teddy', 23, 'Norway', 20000.00 )");
c.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 )");
# 必须提交修改才能生效
conn.commit()
print('插入数据成功')
# 查询persons表中的所有记录,并按age升序排列
persons = c.execute("select name,age,address,salary from persons order by age")
print(type(persons)) # <class 'list'>
result = []
# 将sqlite3.Cursor对象中的数据转换为列表形式
for person in persons:
value = {}
value['name'] = person[0]
value['age'] = person[1]
value['address'] = person[2]
result.append(value) # 将多个字典加入列表
conn.close()
print(type(result))
# 输出查询结果
print(result) # 返回列表包含多个字典
import json
# 将查询结果转换为字符串形式,如果要将数据通过网络传输,就需要首先转换为字符串形式才能传输
resultStr = json.dumps(result)
print(type(resultStr))
print(resultStr)
二.MySQL数据库
MySQL是一个功能强大的网络关系型数据库,支持通过网络多人同时连接和操作数据库。
2.1安装数据库
1.在windows下安装
MySQL下载连接https://dev.mysql.com/downloads/installer
单击第二个Download按钮,下载MySQL的安装程序。然后执行这个安装程序。
在安装的过程种,会要求输入MySQL的root用户名的密码,输入后按提示操作即可完成安装。
安装完成后,打开Windows的计算机管理种的服务列表,如果看到名为MySQL80的服务已经启动,说明MySQL已经安装成功。
2.linux下安装(待补:用的较少)
2.2在Python种使用MySQL
采用pymysql包来操作mysql数据库
pip install pymysql
其中pymysql模块遵循Python DB API 2.0标准
绝大多数的数据库的操作如下:
1.connect函数:连接数据库,根据连接的数据库类型不同,该函数的参数也不同。connect函数返回Connection对象
2.cursor方法:获取操作数据库的Cursor对象。cursor方法属于Connection对象
3.execute方法:用于执行SQL语句,该方法属于Cursor对象
4.commit方法:在修改数据库后,需要调用该方法提交对数据库的修改,commit方法属于Cursor对象。
5.roolback方法:如果修改数据库失败,一般需要调用该方法进行数据库回滚,也就是将数据库恢复成之前的样子
本例通过调用pymysql模块中的对应API对MySQL数据库进行增删改查操作
from pymysql import *
import json
# 打开MySQL数据库,其中127.0.0.1是MySQL服务器的IP,root是用户名,12345678是密码
# test是数据库名
def connectDB():
db = connect("127.0.0.1", "root", "12345678", "test", charset='utf8')
return db
db = connectDB()
# 创建persons表
def createTable(db):
# 获取Cursor对象
cursor = db.cursor()
sql = '''CREATE TABLE persons
(id INT PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
age INT NOT NULL,
address CHAR(50),
salary REAL);'''
try:
# 执行创建表的SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
return True
except:
# 如果发生错误则回滚
db.rollback()
return False
# 向persons表插入4条记录
def insertRecords(db):
cursor = db.cursor()
try:
# 首先将以前插入的记录全部删除
cursor.execute('DELETE FROM persons')
# 下面的几条语句向persons表中插入4条记录
cursor.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (1, 'Paul', 32, 'California', 20000.00 )");
cursor.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (2, 'Allen', 25, 'Texas', 15000.00 )");
cursor.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (3, 'Teddy', 23, 'Norway', 20000.00 )");
cursor.execute("INSERT INTO persons (id,name,age,address,salary) \
VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 )");
# 提交到数据库执行
db.commit()
return True
except Exception as e:
print(e)
# 如果发生错误则回滚
db.rollback()
return False
# 查询persons表中全部的记录,并按age字段降序排列
def selectRecords(db):
cursor = db.cursor()
sql = 'SELECT name,age,salary FROM persons ORDER BY age DESC'
cursor.execute(sql)
# 调用fetchall方法获取全部的记录
results = cursor.fetchall()
# 输出查询结果
print(results)
# 下面的代码将查询结果重新组织成其他形式
fields = ['name', 'age', 'salary']
records = []
for row in results:
records.append(dict(zip(fields, row)))
return json.dumps(records)
if createTable(db):
print('成功创建persons表')
else:
print('persons表已经存在')
if insertRecords(db):
print('成功插入记录')
else:
print('插入记录失败')
print(selectRecords(db))
db.close()
三.非关系型数据库
关系型数据库,数据以二维表形式存储,不过还存在另外一种数据库,这就是非关系型数据库,也可以称为NoSQL.
非关系型数据库主要包括对象数据库、建一值数据库、文档数据库、图像数据库、表格数据库等。本例主要介绍文档数据库MongoDB
3.1文档数据库MongoDB
例如:
如果要保存博客和相关的评论,使用关系型数据库,需要至少建立两个表:t_blogs和t_comments。前者用于保存博文,后者用于保存与博文相关的评论,然后通过键值将两个表关联,t_blogs和t_comments通常是一对多关系。但如果关系更加复杂,就需要关联更多的表,而如果使用MongDB就可以直接将博文以及该博文下的所有评论都放在一个文档中存储,也就是将相关的数据都放到一起,无需关联,查询的速度也就更快了。
3.2下载MongoDB
3.3pymongo
下载
pip install pymongo
在python语言中,文档主要是指列表和字典。Mongodb数据库中没有数据库和表的概念,所以python操作的mongodb存储的的都是列表和字典数据
连接MongDB数据库需要创建MongClient类的实例,连接MongoDB数据库后,就可以按文档的方式操作数据库了
本例使用pymongo模块中提供的API操作MongoDB数据库的过程
from pymongo import *
# 连接MongoDB数据库
Client = MongoClient()
# 打开或创建名为data的collection,collection相当于关系型数据库中的数据库
# 在MongoDB中,collection是文档的集合
db = Client.data
# 或者使用类似引用字典值的方式打开或创建collection
# db = Client['data']
# 定义要插入的文档(字典)
person1 = {"name": "Bill", "age": 55, "address": "地球", "salary": 1234.0}
person2 = {"name": "Mike", "age": 12, "address": "火星", "salary": 434.0}
person3 = {"name": "John", "age": 43, "address": "月球", "salary": 6543.0}
# 创建或打开一个名为persons的文档,persons相当于关系型数据库中的表
persons = db.persons
# 先删除persons文档中的所有数据,以免多次运行程序导致文档中有大量重复的数据
persons.delete_many({'age': {'$gt': 0}})
# 使用insert_one方法插入文档
personId1 = persons.insert_one(person1).inserted_id
personId2 = persons.insert_one(person2).inserted_id
personId3 = persons.insert_one(person3).inserted_id
print(personId3)
'''
也可以使用insert_many方法一次插入多个文档
personList = [person1,person2,person3]
result = persons.insert_many(personList)
print(result.inserted_ids)
'''
# 搜索persons文档中的第一条子文档,相当于关系型数据库中的记录
print(persons.find_one())
print(persons.find_one()['name'])
# 搜索所有数据
for person in persons.find():
print(person)
print('--------------')
# 更新第1个满足条件的文档中的数据,使用update_many方法可以更新所有满足条件的文档
persons.update_one({'age': {'$lt': 50}}, {'$set': {'name': '超人'}}) #
# persons.delete_one({'age':{'$gt':0}}) # 只删除满足条件的第1个文档
# 搜索所有满足age小于50的文档
for person in persons.find({'age': {'$lt': 50}}):
print(person)
print('--------------')
# 搜索所有满足age大于50的文档
for person in persons.find({'age': {'$gt': 50}}):
print(person)
# 输出persons中的文档总数
print('总数', '=', persons.count())