当解析器解析出数据后,接下来就是存储数据了。存储的方式多种多样,除了保存为文档,还可以对接数据库。
1.文件存储
1.1txt文本存储
将数据保存到TXT文本的操作非常简单,而且TXT文本几乎兼容任何平台,但有个缺点,就是不利于检索。所以如果对检索和数据结构要求不高,追求方便第一的话,可采用TXT文本存储。
1.1.1基本实例
这里用requests库获取猫眼电影排行,然后遍历每一个电影名,操作文件对象,进行写入和关闭文件。
import requests
from lxml import etree
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36',
'Cookie': '__mta=141860109.1609416427681.1609416512667.1609418131742.6; uuid_n_v=v1; uuid=F2EBEFF0428E11EBB1AF0F1DB9BFAA15CB5575A235BA430F8B3B568DD758C655; _lxsdk_cuid=1767ee55dc1c8-0723dd96fa7f05-594a2011-1fa400-1767ee55dc1c8; _lxsdk=F2EBEFF0428E11EBB1AF0F1DB9BFAA15CB5575A235BA430F8B3B568DD758C655; _csrf=1dee000e14ef35969dc14838269822aa885606a54f5efe06c32dd954decc8b8b; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1608446730,1609416427; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1609418132; _lxsdk_s=176b8b1c836-b48-ce1-ee2%7C%7C12'}
r = requests.get('https://maoyan.com/board/4',headers=headers)
text = r.text
# print(text)
html = etree.HTML(text)
# print(html)
ret_list = html.xpath('//*[@id="app"]/div/div/div[1]/dl/dd/div/div/div/p/a/@title')
for title in ret_list:
file = open('top10.txt','a',encoding='utf-8')
file.write('\n'.join([title]) + '\n')
file.close()
运行后:
同级目录下会出现一个txt文件,打开里面就是我们刚爬下来的10个电影名。这里需要注意的是格式问题,尤其是2个换行符的使用。
1.1.2打开方式
在上面的实例中,open方法后面第二个参数设置为a,这样每次写入文本时不会清空原文件。下面介绍文件的几种打开方式。
名字 | 方式 |
---|---|
r | 只读方式打开文件,文件指针会放在文件开头。这是一个默认模式 |
w | 写入方式打开文件,如果该文件存在,则覆盖文件,不存在,则创建。 |
b | 二进制方式打开文件,一般不会单独出现,会和r,w,a等协同出现 |
a | 追加方式打开文件,文件已存在,新的内容会被写入到已有的内容之后,文件不存在,则创建 |
+ | 读写补充,一般不单独存在,与其他方式协同,如:w+,就是在w的基础上加入可读方式;r+,就是在r的基础上加上写方式;a+,就是读写方式外加追加方式。 |
这里只给出了5个基本的方式,这些方式可以相互组合。如:rb,rb+,wb,wb+,ab,ab+,a+等等。功能就是几个相加。
1.1.3简化写法
with open('top10.txt','a',encoding='utf-8')as file:
file.write('\n'.join([title])+ '\n')
这个方式可以不用调用close方法关闭文件,在with控制块结束时,文件会自动关闭。如果想把原文清空,可以把a换成w。
1.2JSON文件存储
1.2.1对象和数组
JSON是JavaScript对象标记,它通过对象和数组的组合来表示数据,构造简洁但是结构化成都非常高,是一种轻量级的数据交互格式。
在JavaScript语言中,一切都是对象。因此,任何支持的类型都可以通过JSON来表示。
对象:在JavaScript语言中使用{}包裹起来的内容,数据结构为{key1:value1,key2:value2,…}的键值对结构。
数组:在JavaScript语言中使用[]包裹起来的内容,数据结构为:[“java”,“javascript”,“vb”]的索引结构。
所以,一个JSON对象可以写为如下格式:
[{
"name":"pachong",
"type":"txt"
},{
"name":"dierqi",
"age":"20"
}]
中括号包围的相当于列表类型,列表中的每个元素可以是任意类型,这个示例中它是字典类型,由大括号包围。
JSON可以由以上两种形式自由组合而成,可以无限次嵌套,结构清晰,是数据交互的极佳方式。
1.2.2读取JSON
python提供了简单的JSON库来实现JSON文件的读写操作,我们可以调用JSON的loads方法将文本字符串转为JSON对象,可以通过dumps方法将JSON对象转为文本字符串。
import json
str = '''
[{
"name":"pachong",
"type":"txt"
},{
"name":"dierqi",
"age":"20"
}]
'''
print(type(str))
data= json.loads(str)
print(data)
print(type(data))
结果为:
<class 'str'>
[{'name': 'pachong', 'type': 'txt'}, {'name': 'dierqi', 'age': '20'}]
<class 'list'>
这里使用loads方法将字符串转为JSON对象。由于最外层是中括号,所以最终的类型是列表类型。另外值得注意的是,json的内部数据是必须用双引号包围,不能用单引号。
如果需要读取文件的文本。
import json
with open('data.json','r')as file:
str = file.read()
data = json.loads()
print(data)
结果为:
[{'name': 'pachong', 'type': 'txt'}, {'name': 'dierqi', 'age': '20'}]
1.2.3输出JSON
我们可以调用dumps方法将JSON对象转化为字符串。
import json
str = '''
[{
"name":"爬虫",
"type":"txt"
},{
"name":"dierqi",
"age":"20"
}]
'''
str = json.loads(str)
with open('data.json','w')as file:
file.write(json.dumps(str,indent=2,ensure_ascii=False))
结果为:
[
{
"name": "爬虫",
"type": "txt"
},
{
"name": "dierqi",
"age": "20"
}
]
这里首先定义str,然后使用loads方法转换为json格式,然后再写入文件,这里用dumps方法转换为字符串,才可写入文件。这里的indent指缩进字符个数,ensure_ascii设置为False,那么中文就不会被转码。
1.3CSV文件存储
1.3.1写入
CSV,全称Comma-Separated Values,中文可以叫做逗号分隔值或者字符分隔值,其文件以存文本形式存储表格数据。
import csv
with open('data.csv','w')as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['id','name','age'])
writer.writerow(['101','zj','20'])
writer.writerow(['102','zjj','22'])
生成的文本用wps,或者excel打开就是一个表格了。
这里主要是要注意这些方法和格式的使用。这里输出时,是默认用逗号分隔,我们可以在csv.writer(csvfile,delimiter=’ '),这样就是以空格分隔,当然也可以自己定义分隔符。
我们还可以调用writerows()方法写入多行。
import csv
with open('data.csv','w')as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['id','name','age'])
writer.writerows([['101','zj','20'],['102','zjj','22']])
这里需要注意的是,里外两层[]的使用。
但是在一般情况下,爬虫爬取的都是结构化数据,我们一般会用字典来表示。在csv库中也提供了字典的写入方式,示例如下:
import csv
with open('data.csv','w')as csvfile:
fieldnames = ['id','name','age']
writer = csv.DictWriter(csvfile,fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'id':'101','name':'zj','age':20})
writer.writerow({'id':'102','name':'zjj','age':22})
这里首先定义2个字段,用fieldnames表示,然后将其传给DictWriter来初始化一个字典写入对象,接着可以调用writerheader()方法写入头信息,然后调用writeow()方法传入相应字典即可。如果需要追加的话,就将w改成a.如果遇到中文转码问题,就在’w’后面加上encoding=‘utf-8’.
1.3.2读取
我们同样可以使用csv库读取csv文件
import csv
with open('data.csv','r',)as file:
reader = csv.reader(file)
for row in reader:
print(row)
输出的是一个个列表,也就是你输入时的格式。我们构造Reader对象,通过遍历输出了每行的内容,每一行都是一个列表形式,如果包含中文,请指定文件编码为 utf-8.
当然,还有更简洁的方式:
import pandas as pd
df = pd.read_csv('data.csv')
print(df)
结果为:
id name age
0 101 zj 20
1 102 zjj 22
这种方法,在数据分析时用得很多。
2关系型数据库存储
这里的关系型数据库,是基于关系模型的数据库,他的存储方式就是行列组成的表。首先需要你们去安装mysql,建议5.7版本的。教程csdn上都有。-
2.1MySQL的存储
2.1.1连接数据库
import pymysql
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306)
cursor = db.cursor()
cursor.execute('SELECT VERSION()')
data = cursor.fetchone()
print('Database version:',data)
cursor.execute("CREATE DATABASE spiders DEFAULT CHARACTER SET utf8")
db.close()
这里我们调用connect()方法,连接mysql,然后创建了一个名叫spiders的数据库。
需要可视化工具私我。
2.1.2创建表
import pymysql
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,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.close()
这里我们就在spiders数据库下创建了一个名为students的数据表。
2.1.3插入数据
import pymysql
id = '1610200926'
user = 'zjj'
age = '22'
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,db='spiders')
cursor = db.cursor()
sql = 'INSERT INTO students(id,name,age) value(%s,%s,%s)'
try:
cursor.execute(sql,(id,user,age))
db.commit()
except:
db.rollback()
db.close()
这里主要是注意格式的问题,特别需要注意的是,需要执行db对象的commit()方法才能实现数据的插入,这个方法才是真正将语句提交到数据库执行的方法。对于数据插入,更新,删除操作,都需要调用该方法才能生效。
接下来,我们加了一层异常处理。如果执行失败,则调用rollback()执行函数回滚,相当于什么都没有发生。
这里涉及事务的伪命题。事务机制会保证数据的一致性,也就是这件事要么发生了,要么没有发生。比如插入一条数据,不会存在插入一半的情况,要么全部插入,要么不插入,这就是事务的原子性。另外还有一致性,隔离性和持久性。这4个属性通常称为ACID特性,具体如下表:
属性 | 解释 |
---|---|
原子性(atomicity) | 事务是一个不可分割的工作单位,事务中包括的诸多操作要么都做,要么都不做 |
一致性 | 事务必须使数据库从一个一致性状态变到另一个一致性状态 |
隔离性 | 一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰 |
持久性 | 也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响 |
那么我们要说的是,不管是插入,更新和删除操作都是对数据库进行更改的操作,而更改操作都必须为一个事务,所以这些操作的标准写法就是:
try:
cursor.execute(sql)
db.commit()
except:
db.rollback()
这样就可以保证数据的一致性。
上面数据插入的操作是通过构造SQL语句实现的,但是有一个极不方便的地方,比如突然增加了性别字段gender,此时SQL语句就需要改成
sql = 'INSERT INTO students(id,name,age,gender) value(%s,%s,%s,$s)'
这显然不是我们想要的。在很多情况下,我们要达到的效果是插入方法无需改动,做成一个通用方法,只需要传入一个动态变化的字典就好了。所以我们需要改写一下插入方式。
import pymysql
data = {
'id': '1610200926',
'name': 'zj',
'age': 22
}
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,db='spiders')
cursor = db.cursor()
table = 'students'
keys = ','.join(data.keys())
print(keys)
values = ','.join(['%s']*len(data))
print(values)
sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table,keys=keys,values=values)
print(tuple(data.values()))
try:
if cursor.execute(sql, tuple(data.values())):
print('Successful')
db.commit()
except:
print('Failed')
db.rollback()
db.close()
运行结果为:
id,name,age
%s,%s,%s
('1610200926', 'zj', 22)
Successful
这里获取字典的键,然后构造多个%s当作占位符,长度由字典的长度决定,就构造了动态的构成,与之前的效果是一样的。最后,execute方法第一个参数传入sql变量,第二个参数传入data的键值构造的元组,就可以成功插入数据了。
注意:如果之前你用第一种方法构建了一个students表格,请删除原先的表格,再重新创建一个表格才能成功。
2.1.4更新数据
实际的数据抓取过程中,大部分情况下需要插入数据,但是我们关系的是会不会出现重复的数据,如果出现了,我们希望更新数据而不是重复保存一次。另外,就像前面所说的动态构造SQL的问题,这里我们也可以实现一种灵活的去重的方法,如果数据存在,则更新数据;如果数据不存在,则插入数据。另外,这种做法支持灵活的字典传值。
import pymysql
data = {
'id': '1610200926',
'name': 'zjJ',
'age': 22
}
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,db='spiders')
cursor = db.cursor()
table = 'students'
keys = ','.join(data.keys())
print(keys)
values = ','.join(['%s']*len(data))
print(values)
sql = 'INSERT INTO {table}({keys}) VALUES ({values}) ON DUPLICATE KEY UPDATE '.format(table=table,keys=keys,values=values)
print(tuple(data.values()))
update = ','.join(["{key}=%s".format(key=key) for key in data])
print(update)
sql += update
print(sql)
try:
if cursor.execute(sql, tuple(data.values())*2):
print('Successful')
db.commit()
except:
print('Failed')
db.rollback()
db.close()
运行结果为:
id,name,age
%s,%s,%s
('1610200926', 'zjJ', 22)
id=%s,name=%s,age=%s
INSERT INTO students(id,name,age) VALUES (%s,%s,%s) ON DUPLICATE KEY UPDATE id=%s,name=%s,age=%s
Successful
这里在原先sql的基础上加了 ON DUPLICATE KEY UPDATE。这行代码的意思是如果主键存在,就执行更行操作。然后构造update参数,把它加到sql后面,最后我们构造的就是这样:
INSERT INTO students(id,name,age) VALUES (%s,%s,%s) ON DUPLICATE KEY UPDATE id=%s,name=%s,age=%s
!!!!注意:这里在ON DUPLICATE KEY UPDATE后面一定要加一个空格,不然拼接起来会有歧义导致不成功。
然后sql中就由6个%s,所以在后面的execute()方法的第二个参数元组就需要乘以2变成原来的2倍。
2.1.5删除数据
import pymysql
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,db='spiders')
cursor = db.cursor()
table = 'students'
condition = 'age > 20'
sql = 'DELETE FROM {table} WHERE {condition}'.format(table=table, condition=condition)
try:
cursor.execute(sql)
db.commit()
except:
db.rollback()
db.close()
这里的condition有许多,运算符有大于,小于,等于,LIKE等,条件连接符有AND,OR等,可以自由组合。
2.1.6查询数据
import pymysql
db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,db='spiders')
cursor = db.cursor()
table = 'students'
sql = 'SELECT * FROM {table} WHERE age >= 20'
try:
cursor.execute(sql)
print('Count:',cursor.rowcount)
row = cursor.fetchone()
while row:
print('Row:',row)
row = cursor.fetchone()
except:
print('Error')
这里首先定义一个sql语句,查询age>=20的结果,然后调用cursor.rowcount来输出匹配的结果个数。注意这里没有使用fetchall方法,因为它的实现内部有一个偏移指针用来指向查询结果,最开始偏移指针指向第一条数据,去一次之后,指针偏移到下一条数据,这样再取的话,就会取到下一条数据。所以要时刻注意指针的位置。不用fetchall方法的原因,是它是以元组返回所有数据,如果数据量很大,那么占用的开销会非常高。所以这里我们采用了循环的方法,逐条的返回数据。
3非关系型数据库存储
非关系型数据库,NoSQL,全称 Not Only SQL,意为不仅仅是SQL,泛指非关系型数据库。NoSQL是基于键值对的,而且不需要经过SQL层的解析,数据之间没有耦合性,性能非常高。
现在主流的数据库,主要是MongoDB,Redis.
3.1MongoDB存储
3.1.1连接MongoDB,然后插入数据
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
student1 = {
'id':'1629645',
'name':'zjj',
'age':22
}
student2 = {
'id':'16296452',
'name':'zj',
'age':22
}
# result = collection.insert(student1)
result = collection.insert([student1,student2])
# result = collection.insert_one(student1)
# result = collection.insert_many([student1,student2])
这里首先连接数据库,指定本机,和端口。然后指定数据库为tutorrial,如果没有该数据库,会为你创建一个。在指定students集合,有则插入,没有则创建。然后这里给出了4种方法,官方推荐使用insert_one()和insert_many()方法,不过继续用insert也问题不大。
运行之后:
可视化工具私我。
3.1.2查询
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
result = collection.find_one({'name':'zj'})
print(type(result))
print(result)
运行之后:
<class 'dict'>
{'_id': ObjectId('6000852c153249bbf2a95d17'), 'id': '16296452', 'name': 'zj', 'age': 22}
返回结果为字典类型,可以发现,返回的数据中多了一个_id属性,这是在插入过程中自动添加的,所以我们亦可以根据ObjectId来查询,需要导入bson库里面的objectid:
from bson.objectid import ObjectId
如果想查询多条,就使用find方法,会返回一个生成器,需要遍历取到所有的结果,其中每一个结果都是字典类型。
而如果需要较为复杂的查询条件,那么
符号 | 含义 |
---|---|
$lte | 小于等于 |
$gt | 大于 |
$lt | 小于 |
$gte | 大于等于 |
$ne | 不等于 |
$in | 在范围内 |
$nin | 不在范围内 |
示例:
results = collection.find({'age':{'$in':[20.23]}})
results = collection.find({'age':{'$gt':20}})
另外,还可以进行正则匹配查询。
results = collection.find({'name':{'regex':'^M.*'}})
这里的^M.*代表以M开头任意结尾的正则表达式。
还有一些功能符号,例如判断属性是否存在,类型判断。建议在官方文档中康康:MongD官方文档
3.1.3计数
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
count = collection.find().count()
print(count)
count = collection.find({'age':22}).count()
print(count)
这里会返回所有统计的条数,或者统计符合某个条件的数据。返回的数据是一个数值,即符合条件的数据条数。
3.1.4排序与偏移
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
results = collection.find().sort('name',pymongo.ASCENDING)
print([result['name'] for result in results])
结果为:
['zj', 'zjj']
这里的排序优先级为数字>字母,小写>大写,字母少>字母多,字母表顺序。这里pymango.ASCENDING指定升序。如果要降序,可以传入pymongo.DESCENDING。
偏移指,某些情况下我们可能只想取某几个元素,这时就可以利用skip()方法偏移几个位置,比如偏移2,就是忽略前两个元素,得到第三个及以后的元素:
results = collection.find.sort('name',pymongo.ASCENDING).skip(2)
print([result['name'] for result in results])
还有limit方法,会截取前几个数据返回:
results = collection.find.sort('name',pymongo.ASCENDING).skip(2).limit(2)
print([result['name'] for result in results])
值得注意的是,在数据库数量非常庞大的时候,千万级,亿级,最好别用较大的偏移值来查询数据,最好使用查询_id的方法。
3.1.5更新
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
condition = {'age':{'$gt':20}}
result = collection.update_one(condition,{'$inc':{'age':1}})
print(result.matched_count)
这里我们调用update_one方法,我们需要传入两个参数,一个选择符合条件的数据,二就是修改方法。这里是年龄加一。这里只会修改第一条符合条件的数据
还可以修改多条数据。
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
condition = {'age':{'$gt':20}}
result = collection.update_many(condition,{'$inc':{'age':1}})
print(result.matched_count,result.modified_count)
这里会输出匹配数据的条数和影响条数。
3.1.6删除
import pymongo
client = pymongo.MongoClient(host='localhost',port=27017)
db = client.tutorial
collection = db.students
result = collection.delete_one({'name':'zj'})
print(result)
print(result.deleted_count)
result = collection.delete_many({'age':{'$lt':20}})
print(result.deleted_count)
删除较为简单,同样有两种方法,delete_one()和delete_many()方法,你懂的。
3.2Redis存储
Redis使用很多,是基于内存的高效键值型非关系型数据库,存取效率极高,而且支持多种存储数据结构。
3.2.1连接Redis
from redis import StrictRedis
redis = StrictRedis(host='localhost',port=6379,db=1,password='')
redis.set('name','bob')
print(redis.get('name'))
运行结果为:
b'bob'
这里指定端口,然后密码,我没有设置密码,所以为空,db后面是指定第几个数据库。
还有ConnectionPool方法,StrictRedis内部其实就是用host和port等参数来构造一个ConnectionPool.方法为:
from redis import StrictRedis,ConnectionPool
pool = ConnectionPool(host='localhost',port=6379,db=1,password='')
redis = StrictRedis(connection_pool=pool)
# url = 'redis://[:password]@host:port/db'
# url = 'rediss://[:password]@host:port/db'
# url = 'unix://[:password]@/path/to/socket.sock?db=db'
# pool = ConnectionPool.from_url(url)
这里给出的方法与上面的相似,但是Connectionpool还支持url的输入,上面给出了3种方法,分别表示RedisTCP连接,RedisTCP+SSL连接,RedisUNIXsocket连接。
3.2.2Redis的各种操作
说实话,Redis的操作繁多,每种数据类型都有多达十几种方法,为了方便记忆,这里尽量都给出。注意以下所有方法都需要导入redis,然后再这些方法前面加上redis.
1.键操作:
方法 | 作用 |
---|---|
exists(‘name’) | 是否存在name这个键名,即判断一个键是否存在 |
delete(‘name’) | 删除name这个键,即删除一个键 |
type(‘name’) | 判断name这个键类,即判断键类型 |
keys(‘n*’) | 获取所有以n开头的键,即获取所有符合规则的键 |
randomkey() | 获取随机一个键 |
rename(‘name’,‘rename’) | 将name重命名为rename,即重命名键 |
dbsiaze() | 获取当前数据库中键的数目 |
expire(‘name’,2) | 将name键的过期时间设置为2秒,即设定键的过期时间,单位为秒 |
ttl(‘name’) | 获取name键的过期时间,即获取键的过期时间,单位为秒,-1表示永不过期 |
move(‘name’,2) | 将name移动到2号数据库,将键移动到其他数据库 |
flushdb() | 删除当前选择数据库中所有键,注意:慎用,建议别碰。 |
flushall() | 删除所有数据库中所有键,注意:慎用,建议别碰,除非删库跑路。 |
2.字符串操作
方法 | 作用 |
---|---|
set(‘name’,‘bob’) | 为name这个键的value赋值为bob,即给数据库中键赋予value |
get(‘name’) | 返回name这个键的value,返回数据库中键为name的value |
getset(‘name’,‘mike’) | 赋值name为mike并得到上次的value,即为键赋予value,并返回上次的value |
mget([‘name’,‘nickname’]) | 返回name和nickname的value,即返回多个键对应的value |
setnx(‘newname’,‘james’) | 如果newname这个键不存在,则设置value为james,即如果不存在这个键值对,则更新value,否则不变 |
getrange(‘name’,1,4) | 返回键为name的值的字符串,截取索引为1~4的字符,即获取键的value值从start到end的子字符串。substr()与该方法一致,但是substr的end默认为-1,即结尾 |
append(‘name’,‘ok’) | 在键为name的值后追加ok,即键为name的string的值附加value |
decr(‘age’,1) | age对应的值减1,若不存在,则创建并设置为-1,即键为name的value减值操作,默认为1,键不存在则创建并将value设置为-amount |
incr(‘age’,1) | age对应的值增1,若不存在,则会创建并设置为1,即键为name的value增值操作,默认为1,键不存在则创建并将value设置为amount |
mset({‘name1’:‘mike’,‘name2’:‘zjj’}) | 批量赋值 |
msetnx({‘name3’:‘yj’,‘name4’,‘zj’}) | 在name3和name4均不存在时才设置值 |
3.列表操作
方法 | 作用 |
---|---|
rpush(‘list’,1,2,3) | 在键为list的列表尾添加1,2,3,即在键为list的列表末尾添加值为value的元素,可以传多个。 |
lpush(‘list’,0) | 在键为list的列表头部添加0 ,即在键为list的列表开头加值为value的元素,可以传多个 |
llen(‘list’) | 返回键为list的列表长度,即返回键的长度 |
lrange(‘list’,1,3) | 返回起始索引为1,终止索引为3的索引范围对饮的列表,即返回键为name的列表中start到end之间的元素 |
ltrim(‘list’,1,3) | 保留键为list的索引为1到3的元素,即截取键为list的列表,保留索引为start到end的内容 |
lindex(‘list’,1) | 返回键为list的列表索引为1的元素,即返回键为name的列表中index位置的元素 |
lset(‘list’,1,5) | 将键为list的列表中索引为1的位置赋值5,即返回键为name的列表中index位置的元素赋值,越界则会报错 |
lrem(‘list’,2,3) | 将键为list的列表删除两个3,即返回并删除count个键的列表中值为value的元素 |
lpop(‘list’) | 返回并删除名为list的列表中的第一个元素,即返回并删除键为name的列表中的首元素 |
rpop(‘name’) | 返回并删除名为name的列表中的最后一个元素,即返回并删除键为name的列表的尾元素 |
blpop(‘list’) | 返回并删除键为list的列表中的第一个元素,即返回并删除name的列表的首个元素,如果列表为空,则会一直阻塞等待 |
brpop(‘list’) | 返回并删除键为list的列表中的最后一个元素,即返回并删除name的列表的尾元素,如果列表为空,则会一直阻塞等待 |
rpoplpush(‘list’,‘list2’) | 将键为list的列表尾元素删除并添加到键为list2的列表头部,然后返回 |
4.集合操作
方法 | 作用 |
---|---|
sadd(‘tags’,‘book’,‘tea’,‘coffee’) | 将键为tags的集合中添加book,tea和coffee这三个内容,即添加元素 |
srem(‘tags’,‘book’) | 从键为tags的集合中删除book |
spop(‘tags’) | 从键为tags的集合中随机删除并返回该元素 |
smove(‘tags’,‘tags2’,‘coffee’) | 从键为tags的集合中删除元素coffee并将其添加到键为tags2的集合中 |
scard(‘tags’) | 获取键为tags的集合中元素的个数 |
sismember(‘tags’,‘book’) | 判断book是否是键为tags的集合元素 |
sinter([‘tags’,‘tags2’]) | 返回键为tags的集合和键为tags2的集合的交集 |
sinterstore(‘inttag’,[‘tags’,‘tags2’]) | 求键为tags的集合和键为tags的集合的交集并将其保存为inttag |
sunion([‘tags’,‘tags2’]) | 返回键为tags的集合和键为tags2的集合的并集 |
sunionstore(‘inttg’,[‘tags’,‘tags2’]) | 返回键为tags的集合和键为tags2的集合的并集并将其保存为inttag |
sdiff([‘tags’,‘tags2’]) | 返回键为tags的集合和键为tags2的集合的差集 |
sdiffstore(‘inttag’,[‘tags’,‘tags2’]) | 求键为tags的集合和键为tags2的集合的差集并将其保存为inttag |
smember(‘tags’) | 返回键为tags的集合的所有元素 |
srandmember(‘tags’) | 随机返回键为tags的集合中的一个元素 |
5.有序集合操作
方法 | 作用 |
---|---|
zadd(‘grade’,100,‘bob’,98,‘mike’) | 向键为grade的zset中添加bob,score为100,和mike,score为98.如果元素存在,则更新其顺序 |
zrem(‘grade’,‘mike’) | 从键为grade的zset中删除mike |
zincrby(‘grade’,‘bob’,-2) | 键为grade的zset中bob的score减2,如果不存在,则添加元素 |
zrank(‘grade’,‘amy’) | 得到键为grade的zset中amy的排名 |
zrevrank(‘grade’,‘amy’) | 得到键为grade的zset中amy的倒数排名 |
zrevrange(‘grade’,0,3) | 返回键为grade的zset中前四名元素 |
zrangebyscore(‘grade’,80,95) | 返回键为grade的zset中score再80和95之间的元素 |
zcount(‘grade’,80,95) | 返回键为grade的zset中score在80到95的元素个数 |
zcard(‘grade’) | 获取键为grade的zset中元素的个数 |
zremrangebyscore(‘grade’,0,0) | 删除键为grade的zset中排名第一的元素 |
zremrangebyscore(‘grade’,80,90) | 删除score在80到90之间的元素 |
6.散列操作
方法 | 作用 |
---|---|
hset(‘price’,‘cake’,5) | 向键为price的散列表中添加映射关系,cake的值为5 |
hsetnx(‘price’,‘book’,6) | 向键为price的散列表中添加映射关系,book的值为6.条件是映射键名不存在时 |
hget(‘price’,‘cake’) | 获取键为price的散列表中键名为cake的值 |
hmget( ‘price’,[‘apple’,‘orange’]) | 获取键为price的散列表中apple和orange的值 |
hmset(‘price’,{‘banana’:2,‘pear’:6}) | 向键为price的散列表中批量添加映射 |
hincrby(‘price’,‘apple’,3) | key为price的散列表中apple的值增加3 |
hexists(‘price’,‘banana’) | 判断键为price的散列表中是否存在banana |
hdel(‘price’,‘banana’) | 从键为price的散列表中删除键名为banana的映射 |
hlen(‘price’) | 从键为price的散列表中获取映射个数 |
hkeys(‘price’) | 从键为price的散列表中获取所有映射键名 |
hvals(‘price’) | 从键为price的散列表中获取所有映射键值 |
hgetall(‘price’) | 从键为price的散列表中获取所有映射键值对 |
3.2.3RedisDump
RedisDump提供了强大的数据导入和到处功能。该工具需要用到虚拟机,利用ruby来安装,具体实现可查安装方法
redis-dump用于到处数据,redis-load用于导入数据。
大多数方法,可以通过redis-dump -h或者redis-load -h 来查看
redis-dump:
redis-dump -u :password@localhost:6379
如果没有密码,
redis-dump -u localhost:6379
还可以在后面加参数,实现一些功能,比如指定某个数据导出,就在后面加上 -d 1。就是指定1号数据库导出。还有 -f adsl,可以指定以adsl开头的数据导出。
redis-load:
< redis_data.json redis-load -u :password@localhost:6379
就可以将json行文件导入到redis数据库中。
4结语
介绍了很多存储方式,用的最多要属,文件存储,mysql和redis存储,尤其时redis用的最多,需要熟练掌握。