# Python3 爬虫学习笔记 C11

TRHX

2019-09-04

Python3 学习笔记 / 爬虫学习

字数统计:

2,779字

阅读时长≈

13分

> Python3 爬虫学习笔记第十一章 —— 【MongoDB数据储存】

# 【11.1】关于 MongoDB

MongoDB 属于非关系型数据库，即 NoSQL（Not Only SQL），NoSQL 是基于键值对的，不需要经过 SQL 层的解析，数据之间没有耦合性，性能极高，非关系型数据库分为以下几种：

- 键值存储数据库：Redis、Voldemort、Oracle BDB 等；
- 列存储数据库：Cassandra、HBase、Riak 等；
- 文档型数据库：CouchDB、MongoDB 等；
- 图形数据库：Neo4J、InfoGrid、Infinite Graph 等。

# 【11.2】MongoDB 基本操作语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    # 创建数据库（如果数据库不存在就创建数据库, 存在就切换到指定的数据库）
    use DATABASE_NAME

    # 查看所有数据库
    show dbs

    # 查看当前所在数据库
    db

    # 删除当前数据库
    db.dropDatabase()

    # 删除集合
    db.COLLECTION_NAME.drop()

    # 创建集合
    db.createCollection("COLLECTION_NAME")

    # 插入文档
    db.COLLECTION_NAME.insert(document)
    db.COLLECTION_NAME.save(document)

    # 更新文档
    db.COLLECTION_NAME.update()

    # 删除文档
    db.COLLECTION_NAME.remove()

    # 查询文档
    db.COLLECTION_NAME.find(query, projection)

# 【11.3】连接 MongoDB

连接 MongoDB 需要导入 pymongo 库，使用 `MongoClient()` 方法，向其传入地址参数 host 和 端口参数 port 即可

    1
    2
    3

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)

也可以直接传入 MongoDB 的连接字符串：

    1
    2
    3

    import pymongo

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

# 【11.4】指定数据库

使用以下语句皆可指定一个名为 spiders 的数据库：

    1

    db = client.spiders

    1

    db = client['spiders']

# 【11.5】指定集合

MongoDB 的每个数据库包含多个集合（collection），类似于关系型数据库 MySQL 中的数据表，使用以下语句皆可指定一个名为 students 的集合：

    1

    collection = db.students

    1

    collection = db['students']

# 【11.6】插入数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    students = {
        'id': '17110105',
        'name': 'TRHX',
        'age': 20,
        'gender': 'male'
    }
    result = collection.insert(students)
    print(result)

在 spiders 数据库的 students 集合里，新建一条学生数据，该数据以字典形式表示，调用 collection 的 `insert()` 方法插入数据，在 MongoDB 中，每条数据都有一个_id 属性来唯一标识。如果没有显式指明该属性，MongoDB 会自动产生一个 ObjectId 类型的_id 属性。`insert()` 方法会在执行后返回 _id 值，在 MongoDB 数据库里面可以看到已经成功插入数据，输出结果：

    1

    5d6f1a4b57b65e1547bb3c24

<fancybox>
</fancybox>

进阶操作：同时插入多条数据，以列表形式传递：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    students1 = {
        'id': '17110105',
        'name': 'TRHX',
        'age': 20,
        'gender': 'male'
    }
    students2 = {
        'id': '17110106',
        'name': 'AAAA',
        'age': 22,
        'gender': 'male'
    }
    result = collection.insert([students1, students2])
    print(result)

输出结果：

    1

    [ObjectId('5d6f2be3cd1721962218a709'), ObjectId('5d6f2be3cd1721962218a70a')]

<fancybox>
</fancybox>

PyMongo 3.x 及以上版本中，推荐使用 `insert_one()` 和 `insert_many()` 方法来分别插入单条记录和多条记录，示例：

插入单条记录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    students = {
        'id': '17110105',
        'name': 'TRHX',
        'age': 20,
        'gender': 'male'
    }
    result = collection.insert_one(students)
    print(result)
    print(result.inserted_id)

返回的是 InsertOneResult 对象，调用其 `inserted_id` 属性获取_id：

    1
    2

    <pymongo.results.InsertOneResult object at 0x0000020ED91A5608>
    5d6f73940fe700c5a7ac19f0

插入多条记录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    students1 = {
        'id': '17110105',
        'name': 'TRHX',
        'age': 20,
        'gender': 'male'
    }
    students2 = {
        'id': '17110106',
        'name': 'AAAA',
        'age': 22,
        'gender': 'male'
    }
    result = collection.insert_many([students1, students2])
    print(result)
    print(result.inserted_ids)

返回的类型是 InsertManyResult，调用 `inserted_ids` 属性可以获取插入数据的_id 列表：

    1
    2

    <pymongo.results.InsertManyResult object at 0x0000021698DD36C8>
    [ObjectId('5d6f68598fa881c69b2e0006'), ObjectId('5d6f68598fa881c69b2e0007')]

# 【11.6】数据查询

事先已经创建好 spiders 数据库和 students 集合，包含以下数据：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    _id:ObjectId("5d6f95d40828142f1dc35fa5")
    id:"17110105"
    name:"TRHX"
    age:20
    gender:"male"

    _id:ObjectId("5d6f95d40828142f1dc35fa6")
    id:"17110106"
    name:"AAA"
    age:20
    gender:"male"

    _id:ObjectId("5d6f95d40828142f1dc35fa7")
    id:"17110107"
    name:"BBB"
    age:19
    gender:"female"

    _id:ObjectId("5d6f95d40828142f1dc35fa8")
    id:"17110108"
    name:"CCC"
    age:22
    gender:"male"

查询方法一：利用 `find_one()` 或 `find()` 方法进行查询， `find_one()` 查询得到的是单个结果，`find()` 则返回一个生成器对象

    1
    2
    3
    4
    5
    6
    7

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    result = collection.find_one({'name': 'TRHX'})
    print(result)

查询 name 为 TRHX 的数据，返回一个字典类型：

    1

    {'_id': ObjectId('5d6f95d40828142f1dc35fa5'), 'id': '17110105', 'name': 'TRHX', 'age': 20, 'gender': 'male'}

查询方法二：根据 ObjectId 查询，查询时需要使用 bson 库里面的 objectid：

    1
    2
    3
    4
    5
    6
    7
    8

    import pymongo
    from bson.objectid import ObjectId

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    result = collection.find_one({'_id': ObjectId('5d6f95d40828142f1dc35fa7')})
    print(result)

查询结果：

    1

    {'_id': ObjectId('5d6f95d40828142f1dc35fa7'), 'id': '17110107', 'name': 'BBB', 'age': 19, 'gender': 'female'}

使用 `find()` 方法查询多条数据：

    1
    2
    3
    4
    5
    6
    7
    8
    9

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    results = collection.find({'gender': 'male'})
    print(results)
    for result in results:
        print(result)

`find()` 方法返回一个生成器对象，遍历得到所有数据，每条数据都是字典类型：

    1
    2
    3
    4

    <pymongo.cursor.Cursor object at 0x00000191F69AAA90>
    {'_id': ObjectId('5d6f95d40828142f1dc35fa5'), 'id': '17110105', 'name': 'TRHX', 'age': 20, 'gender': 'male'}
    {'_id': ObjectId('5d6f95d40828142f1dc35fa6'), 'id': '17110106', 'name': 'AAA', 'age': 20, 'gender': 'male'}
    {'_id': ObjectId('5d6f95d40828142f1dc35fa8'), 'id': '17110108', 'name': 'CCC', 'age': 22, 'gender': 'male'}

在查询条件中加入比较符号进行查询，以下代码实现了年龄大于等于20的数据查询：

    1
    2
    3
    4
    5
    6
    7
    8

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    results = collection.find({'age': {'$gte': 20}})
    for result in results:
        print(result)

符号 `$gte` 表示大于等于，查询结果如下：

    1
    2
    3

    {'_id': ObjectId('5d6f95d40828142f1dc35fa5'), 'id': '17110105', 'name': 'TRHX', 'age': 20, 'gender': 'male'}
    {'_id': ObjectId('5d6f95d40828142f1dc35fa6'), 'id': '17110106', 'name': 'AAA', 'age': 20, 'gender': 'male'}
    {'_id': ObjectId('5d6f95d40828142f1dc35fa8'), 'id': '17110108', 'name': 'CCC', 'age': 22, 'gender': 'male'}

附表：各种比较符号

符号 | 含义 | 示例
--- | --- | ---
$lt | 小于 | {‘age’: {‘$lt’: 20}}
$gt | 大于 | {‘age’: {‘$gt’: 20}}
$lte | 小于等于 | {‘age’: {‘$lte’: 20}}
$gte | 大于等于 | {‘age’: {‘$gte’: 20}}
$ne | 不等于 | {‘age’: {‘$ne’: 20}}
$in | 在范围内 | {‘age’: {‘$in’: [20, 23]}}
$nin | 不在范围内 | {‘age’: {‘$nin’: [20, 23]}}

在查询条件中加入功能符号进行查询，以下代码用正则匹配实现了对名字以 T 开头的学生数据的查询：

    1
    2
    3
    4
    5
    6
    7
    8

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    results = collection.find({'name': {'$regex': '^T.*'}})
    for result in results:
        print(result)

查询结果：

    1

    {'_id': ObjectId('5d6f95d40828142f1dc35fa5'), 'id': '17110105', 'name': 'TRHX', 'age': 20, 'gender': 'male'}

附表：各种功能符号

符号 | 含义 | 示例 | 示例含义
--- | --- | --- | ---
$regex | 匹配正则表达式 | {‘name’: {‘$regex’: ‘^T.*’}} | name 以 T 开头
$exists | 属性是否存在 | {‘name’: {‘$exists’: True}} | name 属性存在
$type | 类型判断 | {‘age’: {‘$type’: ‘int’}} | age 的类型为 int
$mod | 数字模操作 | {‘age’: {‘$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/

# 【11.7】数据计数

调用 `count()` 方法可以统计查询结果有多少条数据，输出结果为一个整数：

    1
    2
    3
    4
    5
    6
    7

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    result = collection.find({'name': {'$regex': '^T.*'}}).count()
    print(result)

# 【11.8】数据排序

调用 `sort()` 方法，向其传入排序的字段及升降序标志即可完成排序：

    1
    2
    3
    4
    5
    6
    7
    8
    9

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    ascending = collection.find().sort('name', pymongo.ASCENDING)
    descending = collection.find().sort('name', pymongo.DESCENDING)
    print('升序排列：', [result['name'] for result in ascending])
    print('降序排列：', [result['name'] for result in descending])

输出结果：

    1
    2

    升序排列： ['AAA', 'BBB', 'CCC', 'TRHX']
    降序排列： ['TRHX', 'CCC', 'BBB', 'AAA']

# 【11.9】数据偏移

利用 `skip()` 方法偏移几个位置，就可以跳过前几条数据，获取偏移量之后的几个数据；利用 `limit()` 方法指定获取前几条数据：

    1
    2
    3
    4
    5
    6
    7
    8
    9

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    ascending = collection.find().sort('name', pymongo.ASCENDING).skip(1)
    descending = collection.find().sort('name', pymongo.DESCENDING).limit(2)
    print('升序排列（偏移量为1，获取后三条数据）：', [result['name'] for result in ascending])
    print('降序排列（限制获取前两条数据）：', [result['name'] for result in descending])

输出结果：

    1
    2

    升序排列（偏移量为1，获取后三条数据）： ['BBB', 'CCC', 'TRHX']
    降序排列（限制获取前两条数据）： ['TRHX', 'CCC']

# 【11.10】更新数据

使用 `update()` 方法，指定更新的条件和更新后的数据即可：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    condition = {'name': 'TRHX'}
    student = collection.find_one(condition)
    student['age'] = 18
    result = collection.update(condition, student)
    print(result)

该代码将 name 为 TRHX 的 age 改为了 18，返回结果仍然是字典形式，ok 代表执行成功，nModified 代表影响的数据条数：

    1

    {'n': 1, 'nModified': 1, 'ok': 1.0, 'updatedExisting': True}

进阶操作：使用 `$set` 操作符对数据进行更新，指定更新的条件和更新后的数据即可，这样做的好处是：只更新指定的 student 字典内存在的字段，如果原先还有其他字段，则不会更新，也不会删除；如果不用 `$set` ，则会把之前的数据全部用 student 字典替换，如果原本存在其他字段，则会被删除

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    condition = {'name': 'TRHX'}
    student = collection.find_one(condition)
    student['age'] = 18
    result = collection.update(condition, {'$set': student})
    print(result)

和插入数据的 `insert()` 方法一样，在 PyMongo 3.x 版本里，推荐使用 `update_one()` 和 `update_many()` 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    condition = {'name': 'TRHX'}
    student = collection.find_one(condition)
    student['age'] = 19
    result = collection.update_one(condition, {'$set': student})
    print(result)
    print(result.matched_count, result.modified_count)

注意：`update_one()` 方法不能直接传入修改后的字典，只能使用 `{'$set': student}` 的形式传入，可以调用 `matched_count` 和 `modified_count` 属性，获取匹配的数据条数和影响的数据条数：

    1
    2

    <pymongo.results.UpdateResult object at 0x00000235A1684508>
    1 1

使用`update_many()` 方法可以将所有符合条件的数据都更新：

    1
    2
    3
    4
    5
    6
    7
    8
    9

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    condition = {'age': {'$gt': 18}}
    result = collection.update_many(condition, {'$set': {'age': 25}})
    print(result)
    print(result.matched_count, result.modified_count)

匹配所有年龄大于 18 的数据，更新条件为将这些所有满足条件的年龄都设置成 25，输出结果如下：

    1
    2

    <pymongo.results.UpdateResult object at 0x00000285CECC45C8>
    4 4

# 【11.11】删除数据

调用 `remove()` 方法并指定删除的条件，此时符合条件的所有数据均会被删除

    1
    2
    3
    4
    5
    6
    7

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    result = collection.remove({'name': 'CCC'})
    print(result)

输出结果：

    1

    {'n': 1, 'ok': 1.0}

同样的，在 PyMongo 3.x 版本里，推荐使用 `delete_one()` 和 `delete_many()` 方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    import pymongo

    client = pymongo.MongoClient(host='localhost', port=27017)
    db = client.spiders
    collection = db.students
    result = collection.delete_one({'name': 'AAA'})
    print(result)
    print(result.deleted_count)
    result = collection.delete_many({'gender': 'female'})
    print(result.deleted_count)

调用 `deleted_count` 属性可以获取删除的数据条数，输出结果：

    1
    2
    3

    <pymongo.results.DeleteResult object at 0x0000024441B245C8>
    1
    1

PyMongo 官方文档：http://api.mongodb.com/python/current/api/pymongo/collection.html

您的喜欢是作者写作最大的动力！❤️

- PayPal
- AliPay
- WeChatPay
- QQPay

Donate

最后更新于 2019年9月24日

爬虫

MongoDB

###### 上一页

#### Python3 爬虫学习笔记 C12

###### 爬虫 图形验证码

###### 下一页

#### Python3 爬虫学习笔记 C10

###### 爬虫 MySQL

#### 评论

## ๑۩ﺴ TRHX ﺴ۩๑

本文目录
欢迎光临

Hexo QQ 交流群 Telegram 交流群

CSDN 内容合伙人

文章分类

- BLOG
  (4)
- CDN
  (1)
- Hexo
  (9)
- Java
  (1)
- Linux
  (2)
- Markdown
  (2)
- Python 数据分析
  (27)
- Matplotlib
  (11)
- NumPy
  (6)
- Pandas
  (10)
- Python3 学习笔记
  (41)
- 基础学习
  (9)
- 学习经验
  (4)
- 爬虫学习
  (18)
- 爬虫实战
  (10)
- VPS
  (1)
- WEB前端
  (2)
- 图床
  (1)

热门标签
12306 3D图 58同城 Ajax BLOG Beautiful Soup CDN Coding Pages DataFrame Deepin Elicpse GitHub Pages Github Github Pages GroupBy HTTPS Hexo ICP备案 IO操作 Index JDBC JS 预加载 LaTeX Markdown Material X Matplotlib MongoDB MySQL NumPy PEP8 Pandas PicGo Pygame Python Redis SEO SQL Server 2012 SSR Selenium Series Ubuntu User-Agent VMware VPS XPath if语句 input()函数 instant.page jsDelivr lxml matplotibrc pyspider requests spfk urllib while循环 主题个性化 代理 位运算 公安备案 函数 函数应用 分割 切片 列表 判断函数 前程无忧 变量 合并数据集 哔哩哔哩 图例 图床 图形验证码 垃圾 备份 子图 字典 字符串函数 安居客 层级索引 年终总结 广播 异常 技巧 拼接 排序 排序函数 操作列表 散点图 数学函数 数据分裂 数据可视化 数据合并 数据替换 数据类型 数据读写 数据重塑 数组 文件 文件储存 无界面浏览器 时间序列 映射 条件函数 条形图 极区图 极坐标图 柱状图 模块 正则表达式 滑动验证码 点触验证码 爬虫 猫眼电影 瓜子二手车 画布 直方图 矩阵 等值线图 等高线图 算术函数 算术运算 类 索引 线性代数 线性图 统计函数 统计描述 统计计算 继承 编辑器 缺失值 网格 肺炎疫情 虎扑论坛 补丁 豆瓣电影 迭代 雷达图 饼状图
最近在听