我们将爬虫抓取的数据获取到后应该将它存储在数据库中供后续的数据分析等操作。现在介绍Python将数据存储在MySql数据库中。
连接数据库
Python2中使用MySqldb连接MySql数据库,在Python3中这个库没办法使用了,推荐使用PyMySql。直接使用pip3 install pymysql
安装即可。
import pymysql
# 打开数据库连接
db = pymysql.connect(host="localhost", user="root", password="*****", port=3306)
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# 使用 execute() 方法执行 SQL 查询
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取单条数据.
data = cursor.fetchone()
print("Database version : %s " % data)
#创建test数据库
cursor.execute("CREATE DATABASE test DEFAULT CHARACTER SET utf-8")
# 关闭数据库连接
db.close()
创建表
import pymysql
import logging
logging.captureWarnings(True)
# 打开数据库连接
db = pymysql.connect("localhost", "root", "zu3.141592653", "test")
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# 使用 execute() 方法执行 SQL,如果表存在则删除
cursor.execute("DROP TABLE IF EXISTS PERSON")
# 使用预处理语句创建表
sql = """CREATE TABLE person (
id int(11) NOT NULL,
FIRST_NAME char(20) NOT NULL,
LAST_NAME char(20) DEFAULT NULL,
AGE int(11) DEFAULT NULL,
SEX char(1) DEFAULT NULL,
INCOME float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8"""
cursor.execute(sql)
# 关闭数据库连接
db.close()
插入数据
import pymysql
import logging
logging.captureWarnings(True)
# 打开数据库连接
db = pymysql.connect("localhost", "root", "zu3.141592653", "test")
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
sql = "INSERT INTO person(id,FIRST_NAME,LAST_NAME,AGE,SEX,INCOME) VALUES(%s,%s,%s,%s,%s,%s)"
try:
cursor.execute(sql,('1','zhang','san','12','m','12000.30'))#传入一个元组
db.commit()
except:
print('出异常,回滚')
db.rollback()
# 关闭数据库连接
db.close()
执行完插入语句后必须执行db.commit()
否则无法将插入语句提交。在后续的更新,删除操作中也必须执行这条语句。使用try except语句将执行语句包裹起来,一旦发生异常使用db.rollback()
进行数据回滚。
通用插入语句
上面的插入语句不通用,表改变了就需要改sql语句了,所以我们需要写一个通用的插入语句。
def insert_db(host,user,pwd,db,table,data):
# 打开数据库连接
db = pymysql.connect(host, user, pwd, db)
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
keys = ",".join(data.keys())
values = ",".join(['%s']*len(data))
sql = "INSERT INTO {table}({keys}) VALUES({values})".format(table=table,keys=keys,values=values)
print('构造的sql语句:',sql)
try:
if cursor.execute(sql, tuple(data.values())):
print("插入成功!")
db.commit()
except:
print('出异常,回滚')
db.rollback()
# 关闭数据库连接
db.close()
data = {
"id":2
"FIRST_NAME":"ZHANG",
"LAST_NAME":"SAN",
"AGE":20,
"SEX":"F",
"INCOME":45000.62
}
insert_db("localhost","root","*******","test","person",data)
将要插入的数据使用字典形式,我们可以很方便的获取key和value,通过k和v可以动态的构造sql语句,这个方法就可以适用于其他的数据表了。
更新数据
最简单的更新sql语句就是类似UPDATE person SET AGE=%s WHERE FIRST_NAME=%s
的了。现在我们将更新和插入结合在一起。如果待插入的数据不存在表(根据主键判断)中就执行插入操作,否则执行更新操作。在实际的爬虫中这也是必要的,防止我们插入过多的重复数据。
import pymysql
def insert_db(host,user,pwd,db,table,data):
'''
:param host: 数据库服务器地址
:param user: 用户名
:param pwd: 密码
:param db: 待连接的数据库
:param table: 操作的表名
:param data: 数据
:return:
'''
# 打开数据库连接
db = pymysql.connect(host, user, pwd, db)
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
keys = ",".join(data.keys())
values = ",".join(['%s']*len(data))
sql = "INSERT INTO {table}({keys}) VALUES({values}) ON DUPLICATE KEY UPDATE".format(table=table,keys=keys,values=values)
update = ",".join([" {key} = %s".format(key=key) for key in data])#注意,{key}前有一个空格
sql += update
print('构造的sql语句:', sql)
try:
if cursor.execute(sql, tuple(data.values())*2):#注意%s数量翻倍了,传入的参数也要翻倍
print("插入成功!")
db.commit()
except:
print('出异常,回滚')
db.rollback()
# 关闭数据库连接
db.close()
data = {
"id":2,
"FIRST_NAME":"ZHANG",
"LAST_NAME":"SAN",
"AGE":30,
"SEX":"F",
"INCOME":45000.62
}
insert_db("localhost","root","zu3.141592653","test","person",data)
可以发现id为2的数据中AGE由原来的20变成了30。
ON DUPLICATE KEY UPDATE作用:当insert已经存在的记录时,执行Update。
ON DUPLICATE KEY UPDATE是MySql中特有的,不是SQL标准语法。
查询数据
# 打开数据库连接
db = pymysql.connect(host, user, pwd, db)
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
sql = "SELECT * FROM person"
try:
if cursor.execute(sql):
print("查询成功!总条目数为:",cursor.rowcount)
one = cursor.fetchone()#fetchone()取出第一条数据,返回元组
print("第一条数据为:",one)
results = cursor.fetchall()#fetchall()取出所有数据,返回二重元组
print(type(results))
for row in results:
print(row)
except:
print('出异常,回滚')
db.rollback()
# 关闭数据库连接
db.close()
我们会发现fetchall()后取出的数据条目不是3,而是2。fetchall()不是获取所有数据吗?
这是因为游标已经不是在第一条数据的位置了(已经执行了fetchone()),所以fetchall()取出了游标之后的所有数据。
同时,我们需要注意fetchall()如果对于特别多的数据量是特别慢的,一般我们循环使用fetchone()获取数据。
删除数据
# 打开数据库连接
db = pymysql.connect(host, user, pwd, db)
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
sql = "DELETE FROM person WHERE id=%s"
try:
if cursor.execute(sql,(1)):
print("删除成功!")
db.commit()
except:
print('出异常,回滚')
db.rollback()
# 关闭数据库连接
db.close()