Python爬虫编程9——MongoDB

目录

SQL与NoSQL的主要区别

MongoDB的优势

MongoDB在Ubuntu中安装

远程连接

MongoDB在Windows中的安装

运行MongoDB

连接MongoDB

MongoDB概念介绍

MongoDB三要素

MongoDB中数据库的基本使用

MongoDB中数据库的基础命令

MongoDB的数据类型

数据库命名规范

MongoDB的增删改查

MongoDB插入数据

单条插入数据

多条插入数据

MongoDB的保存

MongoDB的查询数据

测试数据

查询所有数据

pretty()将结果格式化

查询单条数据

带有条件的查询

比较运算符

范围运算符

逻辑运算符

自定义查询

查询结果操作

查出的数据求总数

limit和skip

映射

排序

修改数据

删除数据

删除表

聚合

常用的管道

测试数据

表达式

$group

$match

Mongodb创建索引

Mongodb和Python的交互

pymongo安装

连接数据库

新增数据

查询数据

修改数据

删除数据

Scrapy对接MongoDB

scrapy的管道文件

settings文件


MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散。因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持查询的语言非常强大,其语法有点类似于面对对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据库建立索引。

SQL与NoSQL的主要区别

  • 在SQL中层级关系:数据库->表->数据
  • 在NoSQL中是:数据库->集合->数据

MongoDB的优势

1.无数据结构限制

(1)没有表结构的概念,每条记录可以有完全不同的结构;

(2)业务开发方便;

{name:'小明',sex:'男'}
{name:'jerry',address:'东北'}
{name:'小红',home:[{'山东'},{江西}]}

2.大数据量和高性能

(1)nosql数据库都具有非常高的读写性能,尤其在大数据量下表现优秀;

3.良好的支持

(1)完善的说明解释文档;

(2)齐全的驱动支持;

MongoDB在Ubuntu中安装

(1)在Linux中安装MongoDB

sudo apt-get install mongodb

(2)开启服务

sudo service mongodb start

(3)关闭服务

sudo service mongodb stop

(4)重启服务

sudo service mongodb restart

注意:如果是系统非正常关闭,这样启动会报错,由于mongodb自动被锁上了,这是需要进入mongodb数据库文件所在的目录(/var/lib/mongodb/),删除目录中的mongodb.lock文件,然后再进行上述操作。

远程连接

需要修改 /etc/mongodb.conf 
打开文件:          
sudo vim /etc/mongodb.conf
注释掉 bind 127.0.0.1

MongoDB在Windows中的安装

网址:MongoDB Community Download | MongoDBhttps://www.mongodb.com/download-center/community

安装配置教程:

Windows下MongoDB的下载安装、环境配置 - chy_18883701161 - 博客园 (cnblogs.com)https://www.cnblogs.com/chy18883701161/p/11100560.html

运行MongoDB

1.把MongoDB的bin目录加入到环境变量中

2.执行命令

mongod --dbpath C:\Program Files\MongoDB\Server\4.4\data  # 启动

连接MongoDB

在环境变量设置好的前提下,使用以下命令 mongo 就可以进入到mongo的操作终端了

查看帮助命令:

mongo -help

MongoDB概念介绍

MongoDB三要素

三元素:数据库,集合,文档

(1)文档:就是关系型数据库中的一行,文档是一个对象,由键值对构成,是json的扩展形式;

{"name": "abc", "gender": 1}

(2)集合:就是关系型数据库中的表。可以存储多个文档,结构可以不固定;

{"name": "abc", "gender": 1}
{"name": "abc", "age": 18}
{"title": "abc", "price": 1}

(3)数据库:可以存储多个集合;

MongoDB中数据库的基本使用

(1)查看数据库:show dbs

(2)切换数据库:use 数据库  

(3)查看当前的数据库:db  

(4)删除数据库:db.dropDatabase()

(5)会自动创建数据库use 数据库

(6)查看集合:show tables/show collections

MongoDB中数据库的基础命令

不手动创建集合,向不存在的集合中第一次加入数据时,集合会被创建出来!!!!

(1)手动创建集合 : db.createCollection(name,options)

  • name: 要创建的集合名称
  • options: 可选参数, 指定有关内存大小及索引的选项
db.createCollection('sub',{capped:true,size:10})
  • 参数capped:默认值为false表示不设置上限,值为true表示设置上限
  • 参数size:当capped值为true时,需要制定此参数。表示上限大小,当文档达到上限时,会将之前的数据覆盖,单位为字节

(2)查看集合

show collections

(3)删除集合:db.集合名称.drop()

MongoDB的数据类型

  • String:字符串,必须是有效的UTF-8
  • Boolean:存储一个布尔值,true或者false
  • Integer:整数可以是32位或64位,这取决于服务器
  • Double:存储浮点数
  • Arrays:数组或列表
  • Object:嵌入式文档
  • Null:存储Null值
  • Timestamp:时间戳, 表示从1970-1-1到现在的总秒数
  • Object ID是一个12字节的十六进制数

数据库命名规范

1.不能是空字符串
2.不得含有特殊字符
3.应全部小写
4.最多64个字节
5.数据库名不能与现有系统保留库同名,如admin,local

MongoDB的增删改查

MongoDB插入数据

db.集合名.insert({})  数据格式为json,id不能重复,支持多条插入数据库

单条插入数据

db.jerry_collection.insert({x:1})

多条插入数据

(1)使用循环插入

for(i=3;i<10;i++)db.jerry3.insert({x:i})

(2)字典外嵌套列表插入

db.stu.insert([{"name" : "张三", "hometown" : "长沙", "age" : 20, "gender" : true },
{"name" : "老李", "hometown" : "广州", "age" : 18, "gender" : false },
{"name" : "王麻子", "hometown" : "北京", "age" : 18, "gender" : false },
{"name" : "刘六", "hometown" : "深圳", "age" : 40, "gender" : true },
{"name" : "jerry", "hometown" : "长沙", "age" : 16, "gender" : true },
{"name" : "小永", "hometown" : "广州", "age" : 45, "gender" : true },
{"name" : "老amy", "hometown" : "衡阳", "age" : 18, "gender" : true }])

MongoDB的保存

命令:db.集合名称.save(document)

db.stu.save({_id:ObjectId("5f169b37d74866264ed9a7db"), name:'gj', gender:2})
db.stu.save({name:'gj', gender:2})
db.stu.find()

MongoDB的查询数据

测试数据

db.stu.insert([{"name" : "张三", "hometown" : "长沙", "age" : 20, "gender" : true },
{"name" : "老李", "hometown" : "广州", "age" : 18, "gender" : false },
{"name" : "王麻子", "hometown" : "北京", "age" : 18, "gender" : false },
{"name" : "刘六", "hometown" : "深圳", "age" : 40, "gender" : true },
{"name" : "jerry", "hometown" : "长沙", "age" : 16, "gender" : true },
{"name" : "小永", "hometown" : "广州", "age" : 45, "gender" : true },
{"name" : "老amy", "hometown" : "衡阳", "age" : 18, "gender" : true }])

查询所有数据

db.jerry_collection.find({条件⽂档})

pretty()将结果格式化

db.集合名称.find({条件⽂档}).pretty()

查询单条数据

db.jerry_collection.findOne({条件⽂档})

带有条件的查询

查询x等于100的数据
db.jerry_collection.find({x:100})

查询x等于100,y等于99的
db.jerry_collection.find({x:100,y:99})

比较运算符

等于:默认是等于判断,没有运算符
小于:$lt
小于等于:$lte
大于:$gt
大于等于:$gte

查询y大于等于18的数据
db.jerryn_collection.find({y:{$gte:18}})

范围运算符

使用$in,$nin判断是否在某个范围内查询年龄为18、28的学生
db.jerry_collection.find({age:{$in:[18,28]}})

逻辑运算符

or:使用$or,值为数组,数组中每个元素为json
db.jerry_collection.find({$or:[{age:{$gt:18}},{gender:false}]})

自定义查询

mongo shell 是一个js的执行环境

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

查询年龄大于30的学生
db.jerry_collection.find({
 $where:function() {
     return this.age>30;}
})

查询结果操作

查出的数据求总数

db.jerry_collection.find().count()

limit和skip

limit用于读取指定数量的文档
db.jerryn_collection.find().limit(2)

skip用于跳过指定数量的文档
db.jerry_collection.find().skip(2)

limit和skip同时使用
db.jerry_collection.find().skip(2).limit(2)

映射

指定返回的字段,如果为1则返回改字段,如果为0则除了改字段外所有字段返回。id如果没写会默认返回

db.jerry_collection.find({},{_id:1})

排序

按照年龄升序排序
db.jerry_collection().find().sort({age:1})

按照年龄降序排序
db.jerry_collection().find().sort({age:-1})

修改数据

db.集合名称.update({query}, {update}, {multi: boolean})
  • 参数query:查询条件
  • 参数update:更新操作符
  • 参数multi:可选,默认是false,表示只更新找到的第一条数据,值为true表示把满足条件的数据全部更新
db.jerry_collection.insert({x:100,y:100,z:100})
{ "_id" : ObjectId("59b297dd8fa0c171faae5bc8"), "x" : 100, "y" : 100, "z" : 100 }

db.jerry_collection.update({x:100},{y:99})
修改后数据变为  
{ "_id" : ObjectId("59b297dd8fa0c171faae5bc8"), "y" : 99 }

部分更新
db.jerry_collection.update({x:100},{$set:{y:99}})

如果y:100数据不存在,就插入y:101这条数据,第三个参数为true
db.jerry_collection.update({y:100},{y:101},true)

更新多条
db.jerry_collection.update({y:99},{$set:{y:101}},{multi:true})

删除数据

db.jerry_collection.remove({条件},{justOne:true})  mongoDB为了防止误删除,条件必须写
db.jerry_collection.remove()   删除所有数据,索引不会删除
db.jerry_collection.remove({x:100})

删除表

db.jerry_collection.drop()

聚合

聚合是基于数据处理的聚合管道,每个文档通过一个由多个阶段组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果

常用的管道

$group:将集合中的文档分组,可用于统计结果
$match:过滤数据,只输出符合条件的文档
$sort:将输入文档排序后输出
$limit:限制聚合管道返回的文档书
$skip:跳过指定数量的文档,并返回余下的文档

测试数据

db.stu.insert({name:"a", hometown: '东北', age: 20, gender: true})
db.stu.insert({name:"b", hometown: '长沙', age: 18, gender: false})
db.stu.insert({name:"c", hometown: '武汉', age: 18, gender: false})
db.stu.insert({name:"d", hometown: '华山', age: 40, gender: true})
db.stu.insert({name:"e", hometown: '山东', age: 16, gender: true})
db.stu.insert({name:"f", hometown: '江苏', age: 45, gender: true})
db.stu.insert({name:"g", hometown: '大理', age: 18, gender: true})

表达式

处理输⼊⽂档并输出

语法:表达式:'$列名'

常⽤表达式:

$sum: 计算总和, $sum:1 表示以⼀倍计数
$avg: 计算平均值
$min: 获取最⼩值
$max: 获取最⼤值
$push: 在结果⽂档中插⼊值到⼀个数组中
$first: 根据资源⽂档的排序获取第⼀个⽂档数据
$last: 根据资源⽂档的排序获取最后⼀个⽂档数据

$group

将集合中的文档分组,课用于统计结果

  • _id表示分组的依据,使用某个字段的格式为 '$字段'

按照gender分组

db.students.aggregate(
    {$group:{_id:'$gender',count:{$sum:1}}}
)

按照gender分组,获取不同组的平均年龄

db.students.aggregate(
    {$group:{_id:'$gender',count:{$sum:1},avg_age:{$avg:"$age"}}}
)

$match

match是管道命令,能将结果交给后一个管道

查询年龄大于20的学生

db.students.aggregate(
    {$match:{age:{$gt:20}}}
)

查询年龄大于20的男生,女生人数

db.students.aggregate(
    {$match:{age:{$gt:20}}},
    {$group:{_id:'$gender',count:{$sum:1}}}
)

Mongodb创建索引

1. 为什么mongdb需要创建索引

  • 加快查询速度
  • 进行数据的去重

2. mongodb创建简单的索引方法

  • 语法:db.集合名.ensureIndex({属性:1}),1表示升序, -1表示降序

3. 创建索引前后查询速度对比

测试:插入10万条数据到数据库中

插入数据

for(i=0;i<100000;i++){db.test.insert({name:'test'+i,age:i})}

创建索引前

db.test.find({name:'test9999'})
db.test.find({name:'test9999'}).explain('executionStats') # 显示查询操作的详细信息

创建索引

db.test.ensureIndex({name:1})

创建索引后

db.test.find({name:'test9999'}).explain('executionStats')

4. 索引的查看

默认情况下_id是集合的索引

查看方式:db.集合名.getIndexes()

5. 删除索引

语法:db.集合名.dropIndex({'索引名称':1})

db.test.dropIndex({name:1})
db.test.getIndexes()

Mongodb和Python的交互

pymongo安装

pip install pymongo

连接数据库

方式一
client = MongoClient()
方式二 指定端口和地址
client = MongoClient('localhost',27017)

新增数据

from pymongo import MongoClient
from datetime import datetime

class TestMongo(object):
    def __init__(self):
        self.client = MongoClient('mongodb://localhost:27017/')
        # 也可以指定连接的集合client['admin']['students']
        self.db = self.client['admin']
        # print(self.client.database_names())

    def add_one(self):
        post = {'title':'标题','content':'内容','created_at':datetime.now()}
        # db.students   students 是表明
        res = self.db.students.insert_one(post)
        return res
        
    def add_more(self):
        data_list = [{"name":"test{}".format(i)} for i in range(5)]
        res = self.db.students.insert_many(data_list)
        return res
    

mongo = TestMongo()
res = mongo.add_one()
插入的ID
print(res.inserted_id)

查询数据

from bson.objectid import ObjectId
查询一条数据
def get_one(self):
    return self.db.students.find_one()

查询多条数据
def get_more(self):
    return self.db.students.find()

根据记录的ID查询数据
def get_from_id(self,id):
    return self.db.students.find_one({'_id':ObjectId(id)})

查询一条数据 
res = mongo.get_one()
查询多条数据
res = mongo.get_more()
for i in res:
	print(i)
根据记录的ID查询数据
res = mongo.get_from_id('5b83e8a1b594c32e8c70c1f7')
print(res)

修改数据

修改单条数据
def update(self):
    res = self.db.students.update_one({'title':'标题'},{'$set':{'title':'title-2'}})
    # 匹配的数据条数
    print(res.matched_count)
    # 影响的数据条数。
    print(res.modified_count)

修改多条
def update_more(self):
    res = self.db.students.update_many({},{'$set':{'x':1}})
    print(res.matched_count)
    print(res.modified_count)
    res = self.db.students.update({'x':2},{'$set':{'x':3}},True)
    
res = mongo.update()
res = mongo.update_more()

删除数据

删除一条
def delete_one(self):
    res = self.db.students.delete_one({'title':'title-2'})
    print(res.deleted_count)

删除多条
def delete_more(self):
    res = self.db.students.delete_many({'x':2})
    print(res.deleted_count)
    
res = mongo.delete_one()
res = mongo.delete_more()

Scrapy对接MongoDB

scrapy的管道文件

from itemadapter import ItemAdapter
import pymongo


class MongoDBPipelines:
    def __init__(self, conn, database):
        self.conn = conn
        self.database = database

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            # 获取全局配置的信息
            conn=crawler.settings.get('MONGODB_CONNECTION_STRING'),
            database=crawler.settings.get('MONGODB_DATABASE')
        )

    def open_spider(self, spider):
        # 创建连接
        self.client = pymongo.MongoClient(self.conn)
        # 连接数据库
        self.db = self.client[self.database]

    def process_item(self, item, spider):
        # 集合名称
        # name = 'text'
        # 默认item类名
        name = item.__class__.__name__
        self.db[name].insert_one(dict(item))

        return item

    def close_spider(self, spider):
        # 关闭连接
        self.client.close()

settings文件

MONGODB_CONNECTION_STRING = '端口号'
MONGODB_DATABASE = '数据库名称'

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值