Python3编写网络爬虫12-数据存储方式五-非关系型数据库存储

非关系型数据库存储

NoSQL 全称 Not Only SQL 意为非SQL 泛指非关系型数据库。
基于键值对 不需要经过SQL层解析 数据之间没有耦合性 性能非常高。

非关系型数据库可细分如下:

键值存储数据库: 代表有Redis、Voldemort、和Oracle BDB等。
列存储数据库:代表有Cassandra、HBase、和Riak等。
文档型数据库:代表有CouchDB、Mongodb等。
图形数据库:代表有Neo4J、InfoGrid、Infinite、Graph等。

对于爬虫的数据存储来说,一条数据可能存在某些字段提取失败而缺失的情况,而且数据可能随时调整。
如果使用关系型数据库 需要提前建表 如果存在数据嵌套关系 需要序列化操作才可以存储。
如果使用非关系型数据库就可以避免一些麻烦,更简单高效。

1.MongoDB存储

简介:MongoDB 是由c++ 语言编写的非关系型数据库 是一个基于分布式文件存储的开源数据库系统,
其内容存储形式类似JSON对象,字段值可以包含文档、数组、非常灵活。

安装 : 安装MongoDB 并确保已经运行

官网 https:www.mongodb.com 下载安装

windows : https://www.mongodb.com/download-center/community

安装后 进入MongoDB安装目录 在bin目录下新建同级目录data 进入data 新建子文件夹db 用于存储数据目录

打开命令行 进入bin目录 运行MongoDB服务 : mongod --dbpath "安装路径\data\db"

输出信息 证明启动了mongodb服务(缺点不能关闭命令行)

想办法设置成可以管理的

1.在bin目录下新建同级目录logs 进入目录新建文件mongodb.log 用于保存mongodb日志
(如不过能在目录新建可以在外新建复制进去)

2.打开管理员运行命令行 输入如下内容:
mongod --bind_ip 0.0.0.0 --logpath "mongodb.log文件路径+文件名" --logappend --dbpath "db目录路径" --port 27017 --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install

(含义:绑定IP为任意ip均可访问 指定日志路径,数据库路径和端口 指定服务名) 无报错信息表示服务安装成功。
3. 打开计算机管理 -> 服务 找到MongoDB 启动服务。
4. 添加环境变量 mongo.exe
5. 打开命令行 输入mongo 进入交互模式。

安装: python的PyMongo库

pip install pymongo

验证:

import pymongo
pymongo.version

输出版本信息
证明安装成功

2.连接MongoDB

示例:

import pymongo
client = pymongo.MongoClient(host=‘localhost‘,port=27017)#创建mongodb对象

#也可以写成

client = MongoClient(‘mongodb://localhost:27017/‘)

3.指定数据库

db = client.test

#也可以写成
db = client[‘test‘]

4.指定集合

collection = db.students
collection = db[‘students‘]

5.插入数据

student = {
‘id‘:‘20180001‘,
‘name‘:‘Bod‘,
‘age‘:20,
‘gender‘:‘male‘
}

result = collection.insert(student)
print(result)#返回_id值

在mongodb中 每一条数据都会有一个_id属性来唯一标识 如果没有会自动生成一个Object类型的_id属性。
insert() 方法会在执行后返回_id值

插入多条数据

student1 = {
‘id‘:‘20180001‘,
‘name‘:‘Bod‘,
‘age‘:20,
‘gender‘:‘male‘
}
student2 = {
‘id‘:‘20180002‘,
‘name‘:‘Mike‘,
‘age‘:22,
‘gender‘:‘male‘
}

result = collection.insert([student1,student2])
print(result)#返回对应的_id集合列表

实际上 在3.X版本中 官方不推荐使用了 但是使用也没什么问题

官方推荐 insert_one() 和 insert_many() 区分插入单条数据和多条数据

示例:

result = collection.insert_one(student)
print(result)#返回InsertOneResult对象
print(result.inserted_id)#利用inserted_id 返回_id

result = collection.insert_many([student1,student2])
print(result)#返回InsertManyResult对象
print(result.inserted_ids)#利用inserted_ids 返回_id列表

6.查询数据

find_one() 返回单个结果 查询不到返回None
find() 返回一个生成器对象

示例:

result = collection.find_one({‘name‘:‘Mike‘})
print(type(result))#dict
print(result)

拓展:
也可以根据ObjectId 来查询 需要使用bson库 objectid

from bson import ObjectId

result = collection.find_one({‘_id‘:ObjectId(‘5c126cdf11bede10f06c6184‘)})
print(result)

示例:

results = collection.find({‘age‘:20})
print(results)#结果为cursor类型 相当于生成器
for result in results:
print(result)

如果要查询年龄大于20

示例:

results = collection.find({‘age‘:{‘$gt‘:20}})

比较符号

$lt 大于    {‘age‘:{‘$lt‘:20}}
$gt 小于    ..
$lte    小于等于    ..
$gte 大于等于    ..
$ne 不等于 ..
$in 在范围内    {‘age‘:{‘$in‘:[20,25]}}
$nin 不再范围    {‘age‘:{‘$nin‘:[20,25]}}

也可以用正则匹配查询

例如查询名字以M开头的学生数据

results = collection.find({‘name‘:{‘$regex‘:‘^M.*‘}})

功能符号归类

符号 含义 示例 示例含义

$regex    匹配正则    {‘name‘:{‘$regex‘:‘^M.*‘}}    name以M开头

$exists 属性是否存在    {‘name‘:{‘$exists‘:True}}    name属性存在

$type 类型判断    {‘name‘:{‘$type‘:‘int‘}}    age的类型为int

$mod 数字模操作    {‘name‘:{‘$mod‘:[5,0]}}    年龄模5余0

$text 文本查询    {‘$text‘:{‘$search‘:‘Mike‘}}    text类型的属性中包含Mike字符串

$where 高级条件查询    {‘$where‘:‘obj.fans_count == obj.follows_count‘} 自身粉丝数等于关注数

更多 https://docs.mongodb.com/manual/reference/operator/query/

7.计数

count() 统计查询结果有多少条数据

示例: 查询所有数据条数

count = collection.find().count()
print(count)

异或 加条件

8.排序

sort() 传入排序的字段 及 升降序标志

示例:

results = collection.find().sort(‘name‘,pymongo.ASCENDING)#升序 降序可以使用DESCENDING
# print(results)
print([result[‘name‘] for result in results])

9.偏移

有时我们可能只想获取某几个元素 可以利用 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])

注意:在数据库数据量非常庞大的时候 如千万、亿级别 最好不要使用大的偏移量来查询数据 很可能会导致内存溢出

此时可以使用类似如下操作来查询

from bson.objectid import ObjectId
collection.find({‘_id‘:{‘$gt‘:ObjectId(‘5c126cdf11bede10f06c6184‘)}})

10.更新

update() 方法 指定更新的条件和更新后的数据

示例:

condition = {‘name‘:‘Mike‘}
student = collection.find_one(condition)
sutdent[‘age‘] = 25
result = collection.update(condition,student)
print(result)#ok 执行成功 nModified 影响数据条数

另外也可以使用$set 操作符对数据进行更新

result = collection.update(condition,{‘$set‘:student})

官方推荐 update_one he update_many

result = collection.update_one(condition,{‘$set‘:student})
print(result.matched_count,result.modified_count)#获得匹配数据条数和影响数据条数

11.删除

remove() 指定删除条件 符合条件的所有数据都会被删除

示例:

result = collection.remove({‘name‘:‘Bod‘})
print(result)

官方推荐:

delete_one() 删除一条符合条件的数据 delete_many() 删除所有符合条件的数据

示例:

result = collection.delete_one({‘name‘:‘Mike‘})
print(result)#DeleteResult类型
print(result.deleted_cout)#删除条数
results = collection.delete_many({‘age‘:20})
print(result)
print(results.deleted_cout)#删除条数

12.其他操作

PyMongo 还提供了其他组合方法如:

find_one_and_delete() 查找后删除
find_one_and_replace() 查找后替换
find_one_and_update() 查找后更新 用法与上面方法基本一致

详细用法参考官方文档 此处不再赘述

http://api.mongodb.com/python/current/api/pymongo/collection.html

数据库与集合操作

http://api.mongodb.com/python/current/api/pymongo/

2.Redis 存储

简介:Redis 是一个基于内存的高效的键值型非关系型数据库,存取效率极高,而且支持多种存储数据结构,使用也非常简单。

安装 Redis 地址:https://github.com/MicrosoftArchive/redis/releases

完成后到计算机管理 -> 服务 查看 redis服务

另外也可以下载可视化管理工具 地址官网:https://redisdesktop.com/download 或者github:https://github.com/uglide/RedisDesktopManager/releases

安装redis-py

 pip install redis

验证:

import redis
redis.VERSION #输出版本信息 表示安装成功

如果要做数据导入导出 还需要安装RedisDump

RedisDump是一个用于redis数据导入导出的工具 是基于Ruby实现的 所以要安装redisdump 要先安装Ruby

Ruby 安装地址参考:http://www.ruby-lang.org/zh_cn/documentation/installation 根据平台不同选择不同安装方式

安装完成后 执行gem命令(类似于python中的pip) gem install redis-dump

验证:

redis-dump -V

可以调用表示安装成功

redis 和 strictredis

redis-py库提供两个类Redis 和 Strictredis 来实现Redis的命令操作

Strictredis 实现绝大部分官方命令 例如 set()对应Redis命令的set方法
Redis是Strictredis 的子类 主要功能是向后兼容旧版本库里的方法 例如 Item() 将value 和 num 参数位置互换
官方推荐 Strictredis

2.1 连接Redis

确保本地已经安装Redis 运行在6379端口 密码设置为 foobared

示例:

from redis import StrictRedis

redis = StrictRedis(host=‘localhost‘,port=6379,db=0,password=‘foobared‘)

redis.set(‘name‘,‘Bob‘)#设置键值对
print(redis.get(‘name‘))#输出结果b‘Bob‘

#也可以使用ConnectionPool

from redis import StrictRedis,ConnectionPool

pool = ConnectionPool(host=‘localhost‘,port=‘6379‘,db=0,password=‘foobared‘)
redis = StrictRedis(connection_pool=pool)
print(redis.get(‘name‘))

同样可以获取到

另外ConnectionPool 还支持三种URL来构造 password没有可以省略

redis://[:password]@host:port/db #TCP连接
rediss://[:password]@host:port/db#TCP+SSL连接
unix://[:password]@/path/to/socket.sock?db=db#UNIX socket连接

示例:

from redis import StrictRedis,ConnectionPool

url = ‘redis://:[email protected]:6379/0‘
pool = ConnectionPool.from_url(url)
redis = StrictRedis(connection_pool=pool)
print(redis.get(‘name‘))

2.2 键操作

键的一些判断和操作方法

方法 作用

exists(name)    #判断一个键是否存在

delete(name)    #删除一个键

type(name)    #判断键类型

keys(pattern)    #获取所有符合规则的键

randomkey()    #获取随机的一个键

rename(src,dst)    #重命名键

dbsize()    #获取当前数据库中键的数目

expire(name,time)    #设键的过期时间 单位是秒

ttl(name)    #获取键的过期时间 -1为永不过期

move(name,db)#将键移动到其他数据库

flushdb()    #删除当前选择数据库中所有键

flushall()    #删除所有数据库中的所有键

2.3 字符串操作 最基本的键值对形式存储

set(name,value)    #给数据库中键为name的string赋值为value

get(name)    #返回数据库中键为name的string的value

getset(name,value)    #返回name的string的赋值value 和 上次的value

mget(keys,*args)    #返回多个键对应的value keys为列表

setnx(name,value)    #如果不存在这个键值对 则更新value 否则不变

setex(name,time,value)    #设置对应的值为string类型的value并指定有效期

setrange(name,offset,value)    #设置指定键的value值为子字符串

mset(mapping)    #批量赋值 mapping为字典

msetnx(mapping)    #键均不存在时才批量赋值

incr(name,amount=1)    #键为name的value增值操作默认为1,键不存在则被创建并设为amount

decr(name,amount=1)    #键为name的value减值操作 默认为1,键不存在则创建并将value设置为-amount

append(key,value)    #键为name的string的值附加为value 追加内容

substr(name,start,end=-1)    #返回键为name的string的子串 截取索引

getrange(key,start,end)    #获取键的value值从start到end的子字符串 截取索引

2.4 列表操作 列表内的元素可以重复 而且可以从两端存储

rpush(name,*vaules)    #在键为name的列表末尾添加值为value的元素,value:值可以传多个

lpush(name,*values)    #在键为name的列表头添加值为value的元素,value:值可以传多个

llen(name)    #返回键为name的列表的长度

lrange(name,start,end)    #返回键为name的列表中start至end之间的元素

ltrim(name,start,end)#    截取键为name的列表保留索引为start到end的内容

lindex(name,index)    #返回键为name的列表中index位置的元素

lset(name,index,value)    #给键为name的列表中index位置的元素赋值,越界则报错

lrem(name,count,value)    #删除count个键的列表中值为value的元素

lpop(name)    #返回并删除键为name的列表中的首元素

rpop(name)    #返回并删除键为name的列表中的尾元素

blpop(keys,timeout=0)    #返回并删除名称在keys中的list中的首个元素,如果列表为空,则会一直阻塞等待

brpop(keys,timeout=0)    #返回并删除名称在keys中的list中的尾元素,如果列表为空,则会一直阻塞等待

rpoplpush(src,dst)    #返回并删除名称为src的列表的尾元素,并将该元素添加到名称为dst的列表头部

2.5 集合操作 集合内的元素都是不重复的

sadd(name,*values)    #向键为name的集合中添加元素

srem(name,*values)    #从键为name的元素中删除元素

spop(name)    #随机返回并删除键为name的集合中的一个元素

smove(src,dst,value)    #从src对应的集合中移除元素并将其添加到dst对应的集合中

scard(name)    #返回键为name的集合的元素个数

sismember(name,value)    #测试member是否是键为name的集合的元素

sinter(keys,*args)    #返回所有给定键keys的集合

sinterstore(dest,keys,*args)    #求交集并将交集保存到dest的集合

sunion(keys,*args)    #返回所有给定键的集合的并集

sunionstore(dest,keys,*args)    #求并集并将并集保存到dest的集合

sdiff(keys,*args)    #返回所有给定键的集合的差集

sdiffstore(dest,keys,*args)    #求差集并将差集保存到dest集合

smembers(name)    #返回键为name的集合的所有元素

srandmember(name)    #随机返回键为name的集合中的一个元素,但不删除元素

2.6 有序集合操作

有序集合比集合多了一个分数字段 利用它可以对集合中的数据进行排序

zadd(name,*args,**kwargs)    #向键为name的zset中添加元素member,score用于排序。如果该元素存在则更新其顺序。

zrem(name,*values)    #删除键为name的zset中的元素

zincrby(name,value,amount=1)    #如果在键为name的zset中已经存在元素value,则将该元素的score增加amount否则向该元素集合中添加该元素,其score的值为amount

zrank(name,value)    #返回键为name的zset中元素的排名,按score从小到大排序

zrevrange(name,start,end,withscores=False)    #返回键为name的zset(按score从大到小)中index从start到end的所有元素

zrangebyscore(name,min,max,start=None,num=None,withscores=False) #返回键为name的zset中score在给定区间的元素

zcount(name,min,max)    #返回键为name的zset中score在给定区间的数量

zcard(name)    #返回键为name的zset的元素个数

zremrangebyrank(name,min,max)    #删除键为name的zset中排名在给定区间的元素

zremrangebyscore(name,min,max)    #删除键为name的zset中score在给定区间的元素

2.7 散列操作 可以用name指定一个散列表的名称,表内存储了各个键值对

hset(name,key,value)    #向键为name的散列表中添加映射

hsetnx(name,key,value)    #如果映射键名不存在,则向键为name的散列表中添加映射

hget(name,key)    #返回键为name的散列表中key对应的值

hmget(name,keys,*args)    #返回键为name的散列表中各个键对应的值

hmset(name,mapping)    #向键为name的散列表中批量添加映射

hincrby(name,key,amount=1) #将键为name的散列表中映射的值增加amount

hexists(name,key)    #键为name的散列表中是否存在键名为键的映射

hdel(name,*keys)    #在键为name的散列表中删除键名为键的映射

hlen(name)    #从键为name的散列表中获取映射个数

hkeys(name)    #从键为name的散列表中获取所有映射键名

hvals(name)    #从键为name的散列表中获取所有映射键值

hgetall(name)    #从键为name的散列表中获取所有映射键值对

2.8 RedisDump
(若执行redis-dump报错 :Error connecting to Redis on localhost:6379 (Redis::TimeoutError))
到 ‘C:\Ruby25-x64\lib\ruby\gems\2.5.0\gems\redis-dump-0.4.0\lib\redis‘ 目录下记事本打开dump.rb
ps -o rss= -p #{Process.pid}.to_i 加注释#
执行

redis-dump -h
-u 代表redis连接字符串

-d 代表数据库代号

-a 密码

-s 代表导出之后的休眠时间

-b 将键值编码为base64(对二进制值有用)

-c 代表分块大小 默认是10000

-f 代表导出时的过滤器

-O 代表禁用运行时优化

-V 显示版本

-D 表示开启调试

执行命令

redis-dump -u 127.0.0.1:6379

打印出redis库所有数据

导出为json行文件

redis-dump -u 127.0.0.1:6379 > ./redis_data.jl

也可以指定库 -d 1 空格 | -d1 表示1号数据库
-f 过滤 例如adsl开头 -f adsl:*

redis-load

查看帮助

redis-load -h
-u 代表redis连接字符串

-d 代表数据库代号

-a 密码

-s 代表导出之后的休眠时间

-b 将键值编码为base64(对二进制值有用)

-n 不检测UTF-8编码

-V 显示版本

-D 表示开启调试

导入json行文件

< ./redis_data.jl redis-load -u 127.0.0.1:6379

总结 :
了解redis-py对redis数据库的一些基本操作 还演示了RedisDump对数据的导入导出操作

原文地址:https://www.cnblogs.com/liuxiaosong/p/10337199.html

时间: 2024-10-11 11:44:14

Python3编写网络爬虫12-数据存储方式五-非关系型数据库存储的相关文章

Python3网络爬虫实战-33、数据存储:非关系型数据库存储:MongoDB

NoSQL,全称 Not Only SQL,意为不仅仅是 SQL,泛指非关系型的数据库.NoSQL 是基于键值对的,而且不需要经过 SQL 层的解析,数据之间没有耦合性,性能非常高. 非关系型数据库又可以细分如下: 键值存储数据库,代表有 Redis, Voldemort, Oracle BDB 等. 列存储数据库,代表有 Cassandra, HBase, Riak 等. 文档型数据库,代表有 CouchDB, MongoDB 等. 图形数据库,代表有 Neo4J, InfoGrid, Inf

Python3网络爬虫实战-34、数据存储:非关系型数据库存储:Redis

Redis 是一个基于内存的高效的键值型非关系型数据库,存取效率极高,而且支持多种存储数据结构,使用也非常简单,在本节我们介绍一下 Python 的 Redis 操作,主要介绍 RedisPy 这个库的用法. 1. 准备工作 在本节开始之前请确保已经安装好了 Redis 及 RedisPy库,如果要做数据导入导出操作的话还需要安装 RedisDump,如没有安装可以参考第一章的安装说明. 2. Redis.StrictRedis RedisPy 库提供两个类 Redis 和 StrictRedi

python爬虫11--文件存储之非关系型数据库存储MongoDB

NoSQL,Not Only SQL,不仅仅是SQL,泛指非关系型数据库,基于键值对的,不需要经过SQL层的解析,数据之间没有耦合性,性能高. 非关系型数据库细分如下: 键值存储数据库:Redis.Voldemort.Oracle BDB: 列表存储数据库:Cassandra.HBase.Riak: 文档型数据库:CouchDB.MongoDB: 图形数据库:Neo4j.InfoGrid.Infinite Graph. 爬虫数据使用非关系型数据库原因:简单高效.爬虫数据可能存在某些字段提取失败或

05 Python网络爬虫的数据解析方式

一.爬虫数据解析的流程 1.指定url 2.基于requests模块发起请求 3.获取响应中的数据 4.数据解析 5.进行持久化存储 二.解析方法 (1)正则解析 (2)bs4解析 (3)xpath解析 1. 正则解析 常用正则表达式 1 单字符: 2 . : 除换行以外所有字符 3 [] :[aoe] [a-w] 匹配集合中任意一个字符 4 \d :数字 [0-9] 5 \D : 非数字 6 \w :数字.字母.下划线.中文 7 \W : 非\w 8 \s :所有的空白字符包,括空格.制表符.

python3编写网络爬虫18-代理池的维护

一.代理池的维护 上面我们利用代理可以解决目标网站封IP的问题 在网上有大量公开的免费代理 或者我们也可以购买付费的代理IP但是无论是免费的还是付费的,都不能保证都是可用的 因为可能此IP被其他人使用来爬取同样的目标站点而被封禁或者代理服务器突然故障或者网络繁忙 一旦选用了一个不可用的代理,这势必会影响爬虫的工作效率 1.准备工作 需要安装Redis数据库并启动服务 另外还需要安装aiohttp.requests.redis-py.pyquery.flask库 redis数据库安装 下载地址 h

Python3编写网络爬虫05-基本解析库XPath的使用

一.XPath 全称 XML Path Language 是一门在XML文档中 查找信息的语言 最初是用来搜寻XML文档的 但是它同样适用于HTML文档的搜索 XPath 的选择功能十分强大,它提供了非常简洁的路径选择表达式,另外还提供了超过100个内置函数,用于字符串,数值,时间的匹配以及节点和序列的处理 XPath 于1999年11月16日成为W3C标准 被设计为供XSLT.XPointer.以及其它XML解析软件使用 1 <<< 2 常用规则 3 4 表达式 描述 5 6 node

Python3编写网络爬虫04-爬取猫眼电影排行实例

利用requests库和正则表达式 抓取猫眼电影TOP100 (requests比urllib使用更方便,由于没有学习HTML系统解析库 选用re) 1.目标 抓取电影名称 时间 评分 图片等 url http://maoyan.com/board/4 结果以文件形式保存 2.分析 offset 代表偏移量 如果为n 电影序号为n+1~n+10 每页显示10个 获取100 分开请求10次 offset 分别为0 10 20...90 利用正则提取相关信息 3.抓取页面 import reques

数据存储之非关系型数据库存储----MongoDB存储

MongoDB存储----文档型数据库 利用pymongo连接MongoDB import pymongo client = pymongo.MongoClient(host='localhost', port=27017) # 或 pymongo.MongoClient('mongodb://localhost:23017/') # 默认端口为:27017 # pymongo.MongoClient()方法 指定数据库 # 指定操作test数据库# db = client.test 或 db

大数据时代的数据存储,非关系型数据库MongoDB

在过去的很长一段时间中,关系型数据库(Relational Database Management System)一直是最主流的数据库解决方案,他运用真实世界中事物与关系来解释数据库中抽象的数据架构.然而,在信息技术爆炸式发展的今天,大数据已经成为了继云计算,物联网后新的技术革命,关系型数据库在处理大数据量时已经开始吃力,开发者只能通过不断地优化数据库来解决数据量的问题,但优化毕竟不是一个长期方案,所以人们提出了一种新的数据库解决方案来迎接大数据时代的到来——NoSQL(非关系型数据库). 为什