Python爬虫--数据存储

python

数据存储

txt文件

占坑

代码

实例代码

Json文件

实例代码

csv文件

数据库存储

数据量多且复杂,存储到文件的数据管理不方便,效率较低。

将数据存储到数据库中,方便存储和管理。

关系型数据库

概念:

  • 关系型数据库是建立在关系模型基础的数据库。
  • 借助于集合代数等数学概念和方法处理数据库中的数据。
  • 由多张能互相连接的二维行列表格组成。

MYSQL


mysql优势

  • 开源(可根据需要修改),免费
  • 支持大型数据库,可以处理拥有上千万条记录的大型数据库
  • 核心线程完全是多线程,支持多处理器


mysql安装

sudo apt install mysql-server

启动服务器

  • 启动服务

sudo service mysql start

  • 重启服务

sudo service mysql restart

  • 查看服务进程

ps -axu|grep mysqld

启动客户端

-u 表示用户名, -p 表示密码

mysql -uroot -p  # -p后输入root用户密码

配置支持远程连接

MySQL默认不支持远程连接,只能本主机连接

配置:

  • 找到MySQL配置文件并修改

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

将bind-address=127.0.0.1注释

  • 登录MySQL,修改Host值

登录

mysql -uroot -p

选择使用MySQL数据库

use mysql;

更新,将root原来的 Host值(localhost) 改成 %

localhost 表示只能本地登录,% 表示任何机器都可以登录

update user set Host="%" where User = "root";

刷新权限信息让所做的设置马上生效

flush privileges;

退出登录

exit;

  • 重启服务

sudo service mysql restart

  • 测试远程连接

-h 参数 指定客户端登录的MySQL主机名,登录本机,该参数可省略

如果是远程连接,则必须指定其值是远程主机的IP地址,这里的192.168.1.150就是主机的IP地址

mysql -h192.168.1.150 -uroot -p


数据库命令

查看数据库

show databases;

创建数据库

create database 数据库名 charset=utf8;

删除数据库

drop database 数据库名;

切换数据库

use 数据库名;

查看当前选择的数据库

select database();


表命令

查看当前数据库中所有表

show tables;

创建表

create table 表名(列及类型);

修改表

alter table 表名 add|modify|drop 列名 类型;

删除表

drop table 表名;

查看表结构

desc 表名;

更改表名称

rename table 原表名 to 新表名;

查看表的创建语句

show create table 表名;

增删改查命令

新增

insert into 表名 (field, field, ..., fieldN) values(value, value, ..., valueN);

删除

delete from 表名 [where 条件];

更新

update table_name set field = new-value, field = new-value [where 条件];

查询

select field, field from table_name [where 条件];


使用命令

流程

service mysql start  # 启动mysql

mysql -uroot -p1234 # 登录mysql

create database python default charset=utf8;  # 创建python数据库

use python; # 切换到python数据库

-- 创建grade表(主键表)

create table grade(

id int primary key auto_increment,

name varchar(100) not null

);

-- 创建student表(外键表)

create table student(

id int primary key auto_increment,

name varchar(100) not null,

sex char(1) not null,

phone char(11) unique not null,

address varchar(100) default \'郑州\',

birthday date not null,

gid int not null,

foreign key(gid) references grade(id)

);

-- 年级(grade)表中插入数据

insert into grade(name) values(\'一年级\');

insert into grade(name) values(\'二年级\');

-- 学生(student)表中插入数据

insert into student(name, sex, phone, address, birthday, gid) values(\'王强\', \'男\' ,\'15583678666\' , \'开封\', \'1990-2-4\', 1);

insert into student(name, sex, phone, address, birthday, gid) values(\'李丽\', \'女\', 16683678659\'\', \'郑州\', \'1991-3-12\', 2);

select * from grade;  # 查询年级(grade)表中的数据

select * from student;  # 查询学生表数据

update student set phone = \'16683678657\' where id = 2;  # 更改id为2的学生电话号码

delete from student where id = 1;  # 删除id为1的学生


Python与MySQL交互

安装pymysql模块

pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple

创建连接

\'\'\'Python与MySQL交互-创建连接\'\'\'

import pymysql

获取连接对象

conn = pymysql.Connect(host=\'localhost\', port=3306, db=\'python\', user=\'root\', passwd=\'1234\', charset=\'utf8\')

print(conn)

关闭

conn.close()

说明:

  • MySQL的服务器必须先启动才可以连接成功
  • pymysql.Connect用来创建数据库连接对象
  • 参数

host=\'localhost\', 表示连接主机是本机,也可指定IP地址

port=3306,主机端口号,默认是3306

host=\'localhost\',连接主机,localhost表示连接主机是本机,也可使用指定IP地址

port=3306, 主机端口号,mysql默认端口号为3306,一般不用更改

db=\'python\', 连接的数据库,这里连接的数据库是python

user=\'root\', 用户名

passwd=\'1234\',密码

charset=\'utf8\', 编码格式

  • 连接对象使用完毕后要关闭,释放相关资源

查询和修改

Python与MySQL交互_查询与修改

import pymysql

def select():

\'\'\'查询\'\'\'

try:

# 获取连接对象

conn = pymysql.Connect(host=\'localhost\', port=3306, db=\'python\', user=\'root\', passwd=\'1234\', charset=\'utf8\')

# 创建可执行对象,可以执行SQL语句

cur = conn.cursor()

# 执行SQL语句,并传递参数

cur.execute(\'select * from student where id=%s\', [2])

# 查询一个结果

result = cur.fetchone()

print(result)

# 关闭

conn.close()

except Exception as ex:

print(ex)

def update():

\'\'\'修改\'\'\'

try:

# 创建连接

conn = pymysql.Connect(host=\'localhost\', port=3306, db=\'python\', user=\'root\', passwd=\'1234\', charset=\'utf8\')

# 创建可以执行SQL语句的对象

cur = conn.cursor()

# 执行SQL语句,并传递参数

count = cur.execute(\'update student set name=%s where id=%s\', [\'张三\', 2])

# 判断结果

if count > 0:

print(\'成功\')

else:

print(\'失败\')

# 提交

conn.commit()

# 关闭

conn.close()

except Exception as ex:

print(ex)

if __name__ == \'__main__\':

select()

update()

说明:

  • 如果是增删改,cur执行SQL语句返回值是受影响的行数。
  • 如果是查询,则需要继续调用cur的查询方法,fetchone是查询符合条件的第一个对象,fetchall是查询符合条件的结果集

非关系型数据库

NoSQL(Not Only SQL)

特点

  • 不支持SQL语法
  • 存储数据KV形式
  • NoSQL没有通用语言,每种NoSQL数据库都有各自的API和语法,以及擅长的业务场景

对比

  • 适用场景:关系型数据库适用于关系特别复杂的数据查询场景,非关系型数据库反之
  • 事务特性的支持:关系型数据库对事务支持完善,非关系型数据基本不支持事务
  • 两者取长补短。对于爬虫的数据,可能有缺失值,可能结构不同。

用关系型数据库,建数据库,数据库表,关系约束,数据筛选,或拆分,这样使用效率较低;而非关系型数据库,直接以键值对存储,简单且效率高。

Redis

概述

用key-value存储,NoSQL的一种

值可以是字符串(String),哈希(Hash),列表(List),集合(Sets),有序集合(Sorted Sets)等类型

优势

  • 性能极高:读的速度110000次/s,写的速度是81000次/s
  • 支持的数据类型多:支持Strings,Lists,Hashes,Sets及Ordered Sets等数据类型的操作
  • 原子:Redis的所有操作都是原子性的,同时还支持对几个操作合并后的原子性执行
  • 丰富的特性:Redis还支持publish/subscribe,通知,key过期等特性

安装

1.打开Redis官方网站,下载稳定版本(stable),放到家目录下 cd /home

2.解压安装包

tar -zxvf ./redis.tar.gz  # 解压

3.移动

sudo mv ./redis/ /usr/local/

4.编译

cd /usr/local/redis/

sudo make

5.测试

sudo make test

6.将Redis的命令安装到/usr/local/bin/目录

sudo make install


启动

redis-server  # 启动服务器

redis-cli  # 启动客户端

测试连接

ping  # 打印PONG表示连接成功

远程访问配置

修改redis.conf配置文件

vim /usr/local/redis/redis.conf

注释bind

protected-mode改为no

bind 127.0.0.1

protected-mode no

使用配置文件方式启动

-- 复制配置文件到etc下的redis文件夹中

sudo mkdir /etc/redis/

sudo cp /usr/local/redis/redis.conf /etc/redis

-- 指定配置文件启动

sudo redis-server /etc/redis/redis.conf

停止Redis服务

ps ajx|grep redis  # 找到Redis的进程id

sudo kill -9 redis的进程id


命令操作

Redis地理位置命令

geoadd # 将指定的地理空间位置(纬度,经度,名称添加到指定的key中)

geodist # 返回两个给定位置之间的距离

geohash # 返回一个或多个位置元素的Geohash表示

geopos # 从key中返回所有给定位置元素的位置

georadius # 以给定的经纬度为中心,找出某一半径内的元素

georadiusbymember # 找出位于指定范围内的元素中心点由给定的位置元素决定

Redis键(key)命令

del  # 该命令用于在key存在时删除key

dump # 序列化给定key,并返回被化的值

move # 将当前数据库中的key移动到给定数据库db当中

rename # 修改key的名称

renamenx # 仅当newkey不存在时,将key改名为newkey

exists # 检查给定key是否存在

type # 返回key所储存的值的类型

keys # 查找所有符合给定模式的key

randomkey # 从当前数据库中随机返回一个key

expire # seconds为给定key设置过期时间

expireat # 作用与expire类似,设置key过期时间,接受的时间参数是unix时间戳

persist # 移除key的过期时间,key将持久保持

pttl # 以毫秒为单位,返回key的剩余过期时间

ttl # 以秒为单位,返回给定key的剩余生存时间

Redis字符串(String)命令

set  # 设置指定key的值

get # 获取指定key的值

getrange # 返回key中字符值的子字符

mget # 获取所有(一个或多个)给定key的值

setbit # 对key所储存的字符串值,设置或清除指定偏移量上的位

setex # 将值value关联到key,并将key的过期时间设为seconds(以秒为单位)

setnx # 只有在key不存在时设置key的值

setrange # 用value参数覆写给定key所储存的字符串值,从偏移量offset开始

strlen # 返回key所储存的字符串值的长度

getset # 将给定key的值设为value,并返回key的旧值

mset # 同时设置一个或多个key-value对

msetnx # 同时设置一个或多个key-value对,当且仅当所有给定key都不存在

psetex # 与setex相似,以毫秒为单位设置key的生存时间

incr # 将key中储存的数字值增一

incrby # 将key所储存的值加上给定的增量值

incrbyfloat # 将key所储存的值加上给定的浮点增量值

decr # 将key中储存的数字值减一

decrby # 将key所储存的值减去给定的减量值

append #如果key已经存在并且是一个字符串,则append将value追加到key原来值的末尾

Redis哈希(hash)命令

hdel  # 删除一个或多个哈希表字段

hexists # 查看哈希表key中,指字的字段是否存在

hget # 获取存储在哈希表中指定key的所有字段和值

hgetall # 获取在哈希表中指定keyr所有字段和值

hincrby # 为哈希表key中指定字段的整数值加上增量

hincrbyfloat # 为哈希表上指定字段的浮点数值加上增量

hkeys # 获取所有哈希表中的字段

hlen # 获取哈希表中的字段的数量

hmget # 获取所有给定字段的值

hmset # 同时将多个field-value(域-值)对设置到哈希表key中

hset # 将哈希表中的key中的字段field的值设为value

hsetnx # 只有在字段field不存在时,设置哈项表字段的值

hvals # 获取哈希表中所有值

记忆: hash命令和string命令的区别在于,hash前面多了个h,去了h命令简写都和string命令差不多

Redis列表(List)命令

blpop  # 移出并获取列表的第一个元素,如果列表中没有元素,则会阻塞列表直到等待超时或发现可弹出元素为止

brpop # 移出并获取列表的最后一个元素,如果列表中没有元素,则会阻塞列表直到等待超时或发现可弹出元素为止

brpoplpush # 从列表弹出一个值,将弹出的元素插入另外一个列表蹉返回它;如果列表中没有元素,则会阻塞列表直到等待超时或发现可弹出元素为止

lindex # 通过索引获取列表中的元素

linsert # 在列表的元素前或后插入元素

llen # 获取列表长度

lpop # 移出并获取列表的第一个元素

lpush # 将一个或多个值插入列表头部

lpushx # 将一个或多个值插入已存在的列表头部

lrange # 获取列表指定范围内的元素

lrem # 移除列表元素

lset # 通过索引设置列表元素的值

ltrim # 对一列表进行修剪,也就让列表只保留指定区内的元素,不在指定区间内的元素都将被删除

rpop # 移除并获取列表最后一个元素

rpoplpush # 移除列表的最后一个元素,并将该元素添加到另一个列表并返回

rpush # 在列表中添加一个或多个值

rpushx # 为已存在的列表添加值

Redis集合(set)命令

sadd  # 向集合添加一个或多个成员

srem # 移除集合中一个或多个成员

sismember # 判断member元素是否集合key的成员

smembers # 返回集合中的所有成员

scard # 获取集合的成员数

sscan #迭代集合中的元素

srandmember # 返回集合中一个或多个随机数

spop # 移除并返回集合中的一个随机元素

smove # 将member元素从source集合到destination集合

sdiff # 返回所有给定集合的差集

sdiffstore # 返回所有给定集合的差集并存储在destination集合中

sinter # 返回所有给定集合的交集

sinterstore # 返回所有给定集合的交集并存储在destination集合中

sunion # 返回所有给定集合的并集

sunionstore # 返回所有给定集合的并集要并存储在destination集合中

记忆:s开头命令代表集合(set)命令

Redis有序集合(Sorted Set)命令

zadd  # 添加一个或多个成员,或者更新已存在成员的分数

zrem # 移除一个或多个成员

zscan # 迭代元素

�zscore # 返回成员分数值

zcard # 获取成员数

zincraby # 对指定成员的分数加上增量increment

zranbyscore # 通过分数返回指定区间内成员

zrangebylex # 通过字典区间返回成员

zinterstore # 计算给定的一个或多个的有序集合的交集并存储在新的key中

zunionstore # 计算给定的一个或多个有序集合并集并存储在新的key中

zrank # 返回指定成员的索引

zcount # 计算在指定区间分数的成员数

zlexcount # 计算指定字典区间内成员变量

zrange # 通过索引区间返回指定区间内成员数量

zremrangebylex # 移除给定的字典区间所有成员

zremrangebyrank # 移除给定的排名区间所有成员

zremrangebyscore # 移除给定的分数区间所有成员

zrevrank # 返回指定成员,按分数值递减(从大到小)

zrevrange # 返回指定区间内成员,通过索引,分数从高到低排序

zrevrangebyscore # 返回指定分数区间内成员,分数从高到低排序

Redis HyperLogLog命令

pfadd  # 添加指定元素到HyperLogLog中

pfcount # 返回给定HyperLogLog的基数估算值

pgmerge # 将多个HyperLogLog合并成一个

Redis发布订阅命令

publish  # 将信息发送到指定的频道

pubsub # 查看订阅与发布系统状态

subscribe # 订阅给定的一个或多个频道的信息

psubscribe # 订阅一个或多个符合给定模式的频道

unsubscribe # 只退订给定的频道

punsubscribe # 退订所有给定模式的频道

Redis事务命令

exec  # 执行所有事务块内的命令

discard # 取消事务,放弃执行事务块内的所有命令

multi # 标记一个事务块的开始

watch # 监视一个(或多个)key,如果在事务执行之前这个(这些)key被其他命令所改动,则事务将被打断

unwatch # 取消watch命令对所有key的监视

Redis脚本命令

eval  # 执行Lua脚本

evalsha # 执行Lua脚本

scriptexists # 查看指定的脚本是否已经被在缓存中

scriptflush # 从脚本缓存中移除所有脚本

scriptload # 将脚本script添加到脚本缓存中,但并不立即执行这个脚本

scriptkill # 杀死当前正在运行的Lua脚本

Redis连接命令

bgrewriteaof  # 异步执行一个AOF(Append Only File)文件重写操作

bgsave # 在后台异步保存当前数据库的数据到磁盘

client kill # 关闭客户端连接

client list # 获取连接到服务器的客户端连接列表

client getname # 获取连接的名称

client pause # 在指定时间内终止运行来自客户端的命令

client setname # 设置当前连接的名称

cluster slots # 获取集群节点的映射数组

command # 获取详情数组

command count # 获取总数

command getkeys # 获取给定的所有键

time # 返回当前服务器时间

command info # 获取指定描述的数组

config get # 获取指定配置参数的值

config rewrite # 对启动服务器时所指定的.conf配置文件进行改写

config set # 修改配置参数,无须重启

config resetstat # 重置INFO中的某些统计数据

dbsize # 返回当前数据库的key的数量

debug object # 获取key的调试信息

debug segfault # 让服务器崩溃

flushall # 删除所有数据库的所有key

flushdb # 删除当前数据库的所有key

info # 获取服务器的各种信息和统计数值 , db=

lastsave # 返回最近一次成功将数据保存到磁盘上的时间,以UNIX时间戳格式表示

monitor # 实时打印出服务器接收到的命令,调试用

role # 返回主从实例所属的角色

save # 异步保存数据到硬盘

shutdown # 异步保存数据到硬盘,并关闭服务器

slaveof # 将当前服务器转变为指定服务器的从属服务器

showlog # 管理Redis的慢日志

sync # 用于复制功能的内部命令

Python与Redis交互

安装模块

pip install redis 

创建连接

\'\'\'Python与Redis交互-创建连接\'\'\'

import redis

client = redis.StrictRedis(host=\'localhost\', port=6379, db=0)

print(client)

# 简写

# client = redis.StrictRedis()

说明:

Redis的服务器必须启动才可以连接成功

redis默认无密

redis.StrictRedis用来创建数据库连接对象

参数,

host:连接主机

port:主机端口号

db:要连接的数据库

连接对象不需要手动关闭。

当用Redis和StrictRedis创建连接时,内部实现没有主动创建一个连接,获得的连接是连接池提供的,由连接池管理,所以无法关注连接是否需要主动释放。

连接池有自己关闭连接的接口,一旦调用该接口,所有连接都将被关闭。

增删改查

# Python与Redis交互-增删改查

from redis import *

def insert_update():

\'\'\'新增/修改\'\'\'

try:

# 创建StrictRedis对象,与Redis服务器建立连接

sr = StrictRedis()

# 添加键name,值为python

# 如果键name不存在,则为新增,否则为修改

result = sr.set(\'name\', \'python\')

# 输出响应结果,如果添加成功,则返回True,否则返回False

print(result)

except Exception as e:

print(e)

def select():

\'\'\'查询\'\'\'

try:

# 连接

sr = StrictRedis()

# 获取键name的值

result = sr.get(\'name\')

# 输出键的值,如果键不存在,则返回None

print(result)

except Exception as e:

print(e)

def delete():

\'\'\'删除\'\'\'

try:

# 连接

sr = StrictRedis()

# 删除

result = sr.delete(\'name\')

# 输出响应结果,删除成功,返回受影响的键数,否则返回0

print(result)

except Exception as e:

print(e)

if __name__ == \'__main__\':

insert_update()

select()

delete()

MongoDB

概念

基于分布式(主从复制,负载均衡)文件存储的NoSQL数据库,由C++语言编写,运行稳定,性能高,旨在为Web应用提供可扩展的高性能数据存储解决方案

特性

  • 模式自由:可以把不同结构的文档存储在同一个数据库中
  • 面向集合存储:适合存储对象及JSON形式的数据
  • 完整的索引支持:对任何属性可索引
  • 复制和高可用性:支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制,复制的主要目的是提供冗余及自动故障转移
  • 自动分片以支持云级别的伸缩性:自动分片功能 支持水平的数据库集群,可动态添加额外的机器
  • 丰富的查询:支持丰富的查询表达方式,查询指令使用形式的标记,可轩昂查询文档中内嵌的对象及数组
  • 快速就地更新:查询优化器会分析查询表达式,并生成一个高效的查询计划
  • 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)

优势

  • 更高的写负载
  • 处理很大规模的单表。数据库扩展是非常有挑战性的,当表格大小达到5-10GB时,MySQL表格性能会毫无疑问的降低。如果需要分片并分割数据库,MongoDB很容易实现
  • 不可靠环境保证高可用性。设置副本集(主-从服务器设置)不仅方便,而且很快。此外,使用MongoDB还可以快速,安全及自动化地实现节点(或数据中心)故障转移
  • 使用基于位置的数据查询,查得更快。MongoDB支持二维空间索引,如管道,因此可以快速及精确地从指定位置获取数据据。MongoDB在启动后会将数据库中的数据以文件映射的方式加载到内存中。如果内存资源相当丰富,那么将极大地提高数据库的查询速度,毕竟内存I/O效率比磁盘高很多。
  • 非结构化数据的爆发增长 。增加列在有些情况下可能锁定整个数据库,或者增加负载从而导致性能下降,这个问题通常发生在表格大于1GB的情况。鉴于MongoDB的弱数据结构模式,添加一个新字段不会对旧表格有任何影响,整个过程会非常快速;因此,在应用程序发生改变时,不需要专门的一个DBA(数据库管理员)去修改数据库模式。
  • 技术门槛相对低。如果没有专业的DBA,同时也不需要结构化数据及做join查询,那么MongoDB将会是首选。MongoDB非常适合类的持久化,类可以被序列化成JSON并储存在MongoDB中。需要注意的是,如果期望获得一个更大的规模,就必须要了解一些最佳实践来避免走入误区。

使用

安装

从官网下载安装包,选择合适的版本下载

32bit的MongoDB最大只能存放2GB的数据,64bit就没有限制

mongodb-linux-x86_64-ubuntu.tgz

解压安装包

tar -zxvf mongodb-linux-x86_64-ubuntu.tgz

移动

sudo mv mongodb-linux-x86_64-ubuntu.tgz/ /usr/local/mongodb

新建配置文件mongod.conf,放到/etc目录下,写入6行命令

port=27017

dbpath=/var/lib/mongodb/

logpath=/var/log/mongodb/mongodb.log

fork=true

logappend=true

noauth=true # 无密

创建相关文件和文件

sudo mkdir /var/lib/mongodb/

sudo mkdir /var/log/mongodb/

sudo touch /var/log/mongodb/mongodb.log

创建软链接,方便调用mongod和mongo命令

sudo ln -sf /usr/local/mongodb/bin/mongod /usr/local/sbin/mongod

sudo ln -sf /usr/local/mongodb/bin/mongo /usr/local/sbin/mongo

启动

启动服务器端

mongod

sudo mongod -f /etc/mongod.conf

启动客户端

sudo mongo

查看数据库的状态信息

db.stats()

关闭服务器

use admin 

db.shutdownServer()

常用的数据类型

object id # 文档id

string # 字符串,最常用,必须是有效的UTF-8

boolean # 布尔值,True或False

integer # 整数可以是32位或64位,取决于服务器

double # 浮点值

array # 数组或列表,多个值存储到一个键

object # 用于嵌入式的文档,即一个值为一个文档

null # 存储null值

timestamp # 时间戳

date # 存储当前日期或时间的UNIX时间格式

说明:

object id。每个文档都有一个属性,为_id,保证每个文档的唯一性,可以自己去设置_id插入文档。

如果没有提供,MonoDB为每个文档提供了一个独特的_id,类型为ObjectID.

ObjectID是一个12字节的十六进制数,前4个字节为当前时间戳,后3个字节为机器ID,后2个字节为MongoDB的服务进程id,最后3个字节为简单的增量值

命令操作

use mydb

db.stu.insert([

{

\'name\': "郭靖",

"hometown": \'蒙古\',

"age": 20,

\'gender\': true

},

{

\'name\': \'黄蓉\',

\'hometown\': \'桃花岛\',

\'age\': 18,

\'gender\': false

}

])

数据库命令

db  # 查看当前数据库名称

show dbs # 查看所有数据库名称,列出所有在物理上存在的数据库

use 数据库名称 # 切换数据库

�/*如果数据库不存在,则指向数据库,直到插入数据或创建集合时数据库才被创建。

默认的数据库为test,如果没有创建新的数据库,则集合存放在test数据库中*/

db.dropDatabase() # 删除当前指向的数据库,如果数据库不存在,则什么也不做

db相当于MySQL中的database

集合命令

db.createCollection(name, options)  # 创建集合  

/*name:要创建的集合名称,必须有。db.createCollection(\'stu\')

选项参数options:文档,用于指定集合的配置。

capped:默认False,不设置上限,Ture,设置(集合大小)上限

size:capped值为True时指定,上限大小,文档达到上限时,会覆盖之前数据,单位字节

db.createCollection("sub", {capped:true, size:10})

*/

show collections # 查看当前数据库的集合

db.集合名称.drop() # 删除集合

这里的集合相当于MySQL的表

数据操作命令

db.集合名称.insert(document)  # 新增一条文档信息

/*

db.stu.insert({name:\'qj\', gender:1})

*/

db.集合名称.find() # 查询当前集合所有文档信息

db.集合名称.update(<query>, <update>, {multi:<boolean>})

/*

参数:

query:查询条件

update:更新操作符

multi:可选,默认False,只更新找到的第一条记录,True,把满足条件的文档全部更新

示例:

全文档更新

db.stu.update({name:\'hr\', {name:\'mnc\'}})

指定属性更新

�db.stu.insert({\'name\':\'hr\', gender:0})

db.stu.update({name:\'hr\',{$set:{name:\'hys\'}}})

修改多条匹配到的数据

db.stu.update({}, {$set:{gender:0}}, {multi:true})��*/

db.集合名称.save(document) # 保存

/*

如果文档的_id已存在,则修改;如果文档的_id不存在,则添加

db.stu.save({_id:\'20160102\', \'name\':\'yk\', gender:1})

db.stu.save({_id:\'20160102\', \'name\': \'wyk\'})*/

db.集合名称.remove(<query>, {justOne:<boolean>}) # 删除

/*

参数:

query:删除文档的条件

justOne:设为True或1,则只删除一条,默认为False,删除多条

示例:

只删除一条

db.stu.remove({gender:0}, {justOne:true})

全部删除

db.stu.remove({})*/

这里的文档document相当于MySQL的一行数据,其语法格式相当于JavaScript的JSON对象

数据查询命令

db.集合名称.find({条件文档})  # 根据条件查询,返回结果集

db.集合名称.findOne({条件文档}) # 根据条件查询,返回第一个

db.集合名称.find({条件文档}).pretty() # 将查询的结果格式化

$lt, $lte, $gt, $gte, $ne

/*

等于,默认是等于判断,没有运算符

小于$lt

小于或等于$lte

大于$gt

大于或等于$gte

不等于$ne

示例:

查询名称等于\'qj\'的学生

db.stu.find({name:\'gj\'})

查询年龄大于或等于18的学生

db.stu.find({age:{\$gte:18}})

*/

and, or # 逻辑与,逻辑或 默认是逻辑与

/*

示例:

查询年龄大于或等于18,并且性别为1的学生

db.stu.find({age:{$gte:18},gender:1})

查询年龄大于18或性别为1的学生

db.stu.find({$or:[{age:{$gt:18}}, {gender:1}]})

查询年龄大于18或性别为1的学生,并且学生的姓名为gj

db.stu.find({$or[{age:{$gte:18}}, {gender:1}], name:\'gj\'})

*/

$in, $nin # 是否在某个范围内

/*

查询年龄为18,28的学生

db.stu.find({age:{$in:[18, 28]}})

*/

$regex, // # 编写正则表达式

/*

查询姓黄的学生

db.stu.find({name:/^黄/})

db.stu.find({name:{$regex:\'^黄\'}})

*/

$where # 后写一个函数,返回满足条件的数据

/*查询年龄大于20的学生

db.stu.find({$where:function(){return this.age>20}})

*/

limit() # 用于读取指定数量的文档

/*语法:db.集合名称.find().limit(NUMBER)

参数NUMBER表示要获取文档的条数

未指定,则显示集合跌所有文档

例:查询2条学生信息

db.stu.find().limit(2)

*/

skip() # 用于跳过指定数量的文档

/*语法:db.集合名称.find()/skip(NUMBER)

参数number表示跳过的记录条数,默认为0

示例:

查询从第3条开始的学生信息

db.stu.find().skip(2)

方法limit()和skip()可以一起使用,不分先后

sb.stu.find().limit(4).skip(1)

db.stu.find().skip(1).limit(4)

*/

投影 # 在查询的结果中,只选择必要的字段,而不是一个文档的整个字段

/*

参数为字段与值,值1为显示,值0为不显示

db.stu.find({}, {name:1, gender:1})

db.stu.find({}, {_id:0, name:1, gender:1})

*/

sort() # 用于对结果集进行排序

/*

语法:db.集合名称.find().sort({字段1:1, 字段2:-1,...})

参数1为升序,参数-1为降序

db.stu.find().sort({gender:-1, age:1})

*/

count() # 用于统计结果集中文档条数

/*

语法:db.集合名称.find({条件}).count()

db.集合名称.count({条件})

示例:

db.stu.find({gender:1}).count()

db.stu.count({age:{$gt:20}, gender:1})

*/

distinct() # 对数据进行去重

/*

语法:db.集合名称.distinct(\'去重字段\', {条件})

例:查找年龄大于18的性别(去重)

db.stu.distinct(\'gender\', {age:{$gt:18}})

*/

管道命令

linux:将当前命令的输出结果作为下一个命令的输入

mongodb:具有同样作用,文档处理完毕,通过管道进行下一次处理

$group  # 将集合的文档分组,可用于统计结果

/*

_id表示分组的依据,使用某个字段的格式为\'$字段\'db.stu.aggregate([{$group:{_id:\'$gender\', conter:{$sum:1}}}])

*/

$match # 用于过滤数据,只输出符条件的文档

$project # 修改输入文档的结构,如重命名,增加,删除字段,创建计算结果

$sort # 将输入文档排序后输出

$limit # 限制聚合管道返回的文档数

$skip # 路过指定数量的文档,并返回余下的文档

$limit和$skip # 先写skip,再写limit

$unwind # 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值

Python与MongoDB交互

安装pymongo模块

pip install pymongo

创建连接

# Python与MongoDB交互--创建连接

import pymongo

myclient = pymongo.MongoClient(\'mongodb://localhost:27017/\')

mydb = myclient[\'mydb\']

print(mydb)

myclient.close()

说明:

MongoDB的服务器必须启动才可以连接成功

创建数据库需要使用MongoClient对象,并且指定连接的URL地址和要创建的数据库名

localhost是要连接的主机,也可以用ip地址访问,27017是主机端口号,mydb是要选择的数据库

增删改查

# MongoDB-增删改查

import pymongo

def is_having(mydb):

dblist = myclient.list_database_names()

if \'mydb\' in dblist:

print(\'数据库已存在!\')

else:

print(\'数据库不存在!\')

return mydb

def insert(mydb):

stu = mydb[\'stu\']

_id = stu.insert({

\'name\': \'扫地僧\',

\'hometown\':\'少林寺\',

\'age\': 66,

\'gender\': True

})

print(_id)

def select(mydb):

stu = mydb[\'stu\']

ret = stu.find()

for i in ret:

print(i)

def update(mydb):

stu = mydb[\'stu\']

x = stu.update_many({\'age\': {\'$gt\': 20}}, {\'$inc\': {\'age\': 1}})

print(x.modified_count, \'文档已修改\')

def delete(mydb):

stu = mydb[\'stu\']

x = stu.delete_many({\'age\': {\'$gt\': 20}})

print(x.deleted_count, \'个文档已删除\')

myclient.close()

if __name__ == \'__main__\':

myclient = pymongo.MongoClient(\'mongodb://localhost:27017/\')

mydb = myclient[\'mydb\']

is_having(mydb)

insert(mydb)

select(mydb)

update(mydb)

delete(mydb)

myclient.close()

说明:

在MongoDB中,数据库只有在内容插入后才会创建。也就是说,数据库创建后要创建集合(数据表)并插入一个文档(记录),数据库才会真正创建。

MongoClient对象的list_database_names()获取所有数据

爬豆瓣电影,保存到MongoDB

# 爬豆瓣电影-保存到MongoDB

import requests

import random

import time

import threading

import json

import csv

import pymongo

from lxml import etree

from queue import Queue

class DouBanSpider:

\'\'\'爬虫类\'\'\'

def __init__(self):

self.headers = {\'User-Agent\': \'Mozilla/5.0\'}

self.baseURL = \'https://movie.douban.com/top250\'

# MongoDB客户端对象

self.client = pymongo.MongoClient(\'mongodb://localhost:27017/\')[\'mydb\'][\'douban\']

def loadPage(self, url):

\'\'\'向url发送请求,获取响应内容\'\'\'

# 随机休眠0-2秒,避免爬虫过快,会导致爬虫封禁

time.sleep(random.random() * 2)

return requests.get(url, headers=self.headers).content

def parsePage(self, url):

\'\'\'根据起始url提取所有的url\'\'\'

# 获取url对应的响应内容

content = self.loadPage(url)

html = etree.HTML(content)

# 所有电影节点

node_list = html.xpath(\'//div[@class="info"]\')

# 遍历

for node in node_list:

# 使用字典存储数据

item = {}

# 每部电影的标题

item[\'title\'] = node.xpath(\'.//span[@class="title"]/text()\')[0]

# 每部电影的评分

item[\'score\'] = node.xpath(\'.//span[@class="rating_num"]/text()\')[0]

self.client.insert(item)

print(item)

# 只有在第一页时才获取所有url组成的列表,其他页就不获取

if url == self.baseURL:

return [self.baseURL + link for link in html.xpath(\'//div[@class="paginator"]/a/@href\')]

def startWork(self):

\'\'\'开始\'\'\'

print(\'begin....\')

# 第一个页面的请求,需要返回所有页面链接,并提取第一页的电影信息

link_list = self.parsePage(self.baseURL)

thread_list = []

# 循环发送每个页面的请求,并获取所有电影信息

for link in link_list:

# 循环创建了9个线程,每个线程都执行一个任务

thread = threading.Thread(target=self.parsePage, args=[link])

thread.start()

thread_list.append(thread)

# 父线程等待所有子线程结束,自己再结束

for thread in thread_list:

thread.join()

print(\'end...\')

if __name__ == \'__main__\':

# 创建爬虫对象

spider = DouBanSpider()

# 开始爬虫

spider.startWork()

以上是 Python爬虫--数据存储 的全部内容, 来源链接: utcz.com/z/387085.html

回到顶部