爬取与数据存储
ch5. 数据存储
-
文件存储
- JSON文件存储
-
关系型数据库存储
- Mysql
1. JSON文件存储
1. JSON中的对象和数组
-
对象
格式为{key1:value1, key2:value2}
. 其中键名可以为字符串, 整数, 值可以为任意类型
-
数组
格式为['content1', 'content2', ....]
, 值可以为任意类型
2. JSON的读取
-
json.loads()
: 该方法需要读取对象的格式符合JSON文件格式的要求。输出结果为列表,可以对接过使用索引等操作。-
可以接受字符串,也可以接受文本文件。如:
import json with open('data.json', 'r') as f: str = file.read() data = json.loads(str)
3. JSON的输出
-
-
json.dumps()
: 该方法将json格式的对象转为字符串,若要将其输出至文件,还需要配合write()和open()方法。如:import json data = ...#data是符合json格式的对象 with open('data.json','w', encoding = 'utf-8') as f: file.write(json.dumps(data, ensure_ascii = False)) #若json中含有中文就需在open()中指定encoding=‘utf-8', write()中指定ensure_ascii = False
2. 关系型数据库—MySQL的存储
1. 链接到数据库及相关基本操作
-
pysql.connect(host = 'localhost', user = 'root', password = '*****', port(3306))
: 成功连接后返回一个数据库对象(令之为db),利用该数据库对象我们可以对数据库进行增添改查等操作。参数说明
- host,默认为localhost
- user,登录数据库的用户名
- password,数据库的密码
- port,数据库端口,默认为3306
-
db.close()
: 在操作完毕后需要将数据库对象关闭。 -
db.cursor()
: 对数据库进行各种操作要通过cursor()方法返回的游标(令之为cr)来进行。 -
cr.execute('sqlSentence')
: 执行语句 -
cr.fetchone()
: 取回sql中返回的结果 -
db.roolback()
: 确保操作为原子操作,保持数据的一致性,即若失败则回退 -
db.commit()
: 插入、更行等操作在执行完db.execute()
后还需要执行该方法才能真正是的操作生效
2. 创建表
创建表的操作关键在于sql语句的书写,以如下代码为例:
import pymqsql
db = pymysql.connect(host = 'localhost', user = 'root', password = '******', port = 3306, db = 'spider')
cr = db.cursor()
sqlSen = 'CREATE TABLE IF NOT EXISTS stuents(id VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, age INT NOT NULL, PRIMARY KEY(id))'
cr.execute(sql)
db.close()
3. 插入数据(动态)
-
静态插入语句:用拼接字符串的方式来完成
id = '1716240306' user = 'bob' age = '20' db = pysql.connect(...) cr = db.cursor() sqlSen = 'INSERT INTO students(id, name, age)' values(%s, %s, %s) try: cr.execute(sql, (id, user, age)) db.commit() except: db.roolback()
-
动态插入语句
data = { 'id':'1716240306', 'name':'xzy', 'age':20, 'gender':'male' } tableS = 'studentes'# 用变量保存字段,以便于修改、调用 keysS = ','.join(data.keys())# 用','将data中的键分隔开,以供函数调用使用 valusS = ','.join(['%s'] * len(data))# '[‘%s’] * 3' == '['%s', '%s', '%s’]' sqlSen = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=tableS, keys = keysS, values = valuesS) #str.format()用于填补字符串,填补入字符串中的{},format()中填入要填补的内容,从左向右按序填入。若字串中占位符形式为{argName},则需要在参数中使用argName=value的形式来传递参数 try: if cr.execute(sqlSen, tuple(data.values())): #tuple()元组返回列表,以供sql语句提供参数 print('successful') db.commit() except: print('failed') db.roolback() db.close()
-
不重复的更新数据
data = {
'id':'1716240306',
'name':'xzy',
'age':20,
'gender':'male'
}
tableS = 'students'
keysS = ','.join(data.keys())
valuesS = ','.join(['%s']*len(data))
#['%s']*3 == ['%s','%s','%s']
sqlSen = 'INSERT INTO {table}({keys}) VALUES({values}) ON DUPLICATE KEY UPDATE'.format(table = tableS, keys = kyesS, value = valuesS)
#'ON DUPLICATE KEY UPDATE'表示若主键存在就执行更新操作,否则执行插入操作。
updatePart = ','.join(["{key} = %s".format(key = keyS) for key in data])
#In[13]: (["{key} = %s".format(key = keysS) for key in data])
#Out[13]: ['id = %s', 'name = %s', 'age = %s', 'gender = %s']
sqlSen += updatePart
try:
if cr.execute(sqlSen, tuple(data.values())*2):
#因为在加入更新语句后sqlSen中共有六处需要填进参数,所以需要参数处需要'*2'
db.commit()
print('successful')
except:
db.rollback()
print('failed')
db.close
- 查询数据
sqlSen = 'SELECT * FROM students WHERE age >= 20'
try:
cr.execute(sqlSen)
print('Count:',cr.rowcount)
one = cr.fetchone()
#从sql服务取回了一条结果,随后在sql中的指针自动向后偏移一位
print('one row: ', one)
results = cr.fetchall()
#results保存了sql剩余的所有结果,(有一条结果被fetchone取走)
pritn('results:', results)
for aRow in results:
print(aRow)
except:
print('error')