返回介绍

8.3 更适合爬虫的 MongoDB

发布于 2024-01-26 22:39:51 字数 12843 浏览 0 评论 0 收藏 0

MongoDB是一个基于分布式文件存储的数据库,由C++语言编写,旨在为Web应用提供可扩展的高性能数据存储解决方案。和MySQL不同的,MongoDB是一个介于关系数据库和非关系数据库之间的产品,属于非关系数据库,但是非常像关系型数据库。MongoDB功能比较丰富,非常适合在爬虫开发中用作大规模数据的存储。

8.3.1 安装MongoDB

接下来开始进行MongoDB的安装,以Ubuntu和Windows为例。

1.Ubuntu下安装和配置MongoDB

MongoDB提供了Linux平台上32位和64位的安装包,可以在官网进行下载。下载地址:http://www.mongodb.org/downloads ,如图8-13所示。

图8-13 下载页面

下载压缩包,并解压到新建的mongodb目录下:

·mkdir mongodb

·curl-O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1404-3.2.11.tgz

·tar-zxvf mongodb-linux-x86_64-ubuntu1404-3.2.11.tgz

·mv mongodb-linux-x86_64-ubuntu1404-3.2.11/mongodb/

MongoDB的可执行文件位于mongodb-linux-x86_64-ubuntu1404-3.2.11文件夹下的bin目录下,将bin目录所在路径添加到环境变量中。本人Ubuntu系统所使用的bin目录路径为/home/ubuntu/mongodb/mongodb-linux-x86_64-ubuntu1404-3.2.11/bin。

  export  PATH=/home/ubuntu/mongodb/mongodb-linux-x86_64-ubuntu1404-3.2.11/bin:$PATH

接着需要创建数据库路径,MongoDB的数据存储默认在data目录的db目录下。

  mkdir -p /data/db

这个时候,进入bin目录,运行mongod服务,效果如图8-14所示。

  sudo ./mongod

图8-14 启动mongodb服务

如果你创建数据库的目录不是在根目录下,可以使用--dbpath参数指定。示例如下:

  sudo ./mongod --dbpath /home/data/db

2.Windows下安装和配置MongoDB

下载Windows下的安装包,双击开始安装,设置安装路径为D:\Program Files\MongoDB\ Server\3.3\,安装效果如图8-15所示。

图8-15 安装mongoDB

安装完mongoDB,将mongodb下的bin目录添加到PATH环境变量中。最后配置mongoDB的存储路径,例如在D盘下建立D:\mongodb\data\db目录结构。

当以上的工作都完成后,就可以在命令行中启动mongoDB服务,输入:mongod--dbpath D:\mongodb\data\db,运行效果如图8-16所示。

图8-16 启动mongoDB

大家可以将这mongod--dbpath D:\mongodb\data\db做成一个批处理文件,方便使用。

除了在命令行中启动,还可以将mongoDB注册成一个服务,在系统启动时自动运行。命令格式如下:

mongod --bind_ip yourIPadress --logpath <logpath> --logappend --dbpath <dbpath> --port yourPortNumber --serviceName "YourServiceName" --serviceDisplayName "YourServiceName" --install

mongoDB启动的参数说明如表8-10所示。

表8-10 mongoDB启动的参数说明

例如先将命令行窗口以管理员权限启动,并输入命令:mongod--logpath“D:\mongodb\log.txt”--dbpath“D:\mongodb\data\db”--install。注册完成后,接着输入net start mongodb就可以启动服务,效果如图8-17所示。

图8-17 注册MongoDB服务

如果想连接MongoDB进行数据库操作,只需要在命令行中输入mongo,就可以进入shell操作界面,如图8-18所示。

图8-18 MongoDB shell界面

8.3.2 MongoDB基础

MongoDB属于NoSQL数据库,里面的一些概念和MySQL等关系型数据库大不相同。MongoDB中基本的概念是文档、集合、数据库,下面通过表8-11将SQL概念和MongoDB中的概念进行对比。

表8-11 SQL概念和MongoDB中的概念进行对比

1.MongoDB中文档、集合、数据库的概念

文档:文档是MongoDB中数据的基本单元(即BSON),类似关系型数据库中的行。文档有唯一的标识“_id”,数据库可自动生成。文档以key/value的方式,比如{“name”:“qiye”,“age”:20},可类比数据表的列名,以及列对应的值。下面通过三个不同的文档来说明文档的特性。

·文档1:

·{“name”:“qiye”,“age”:24,“email”:[“qq_email”,“163_email”,“gmail”],“chat”:{“qq”:“11111”,“weixin”:“11111”}}

·文档2:

·{“Name”:“qiye”,“Age”:24,“email”:[“qq_email”,“163_email”,“gmail”],“chat”:{“qq”:“11111”,“weixin”:“11111”}}

·文档3:

·{“name”:“qiye”,“email”:[“qq_email”,“163_email”,“gmail”],“age”:24,“chat”:{“qq”:“11111”,“weixin”:“11111”}}

主要说明三个文档的特性:

·文档的键值对是有序的,顺序不同文档亦不同。

·文档的值可以使字符串、整数、数组以及文档等类型。

·文档的键是用双引号标识的字符串(常见的);除个别例外,可用任务UTF-8字符。要求如下:键不能含有“\0”(空字符),这个字符用来标识键的结尾;“.”和“$”被保留,存在特别含义,最好不要用来命名键名;以“_”开头的键是保留的,建议不要使用。

·文档区分大小写以及值类型,比如:{“name”:“qiye”,“age”:24}和{“name”:“qiye”,“age”:“

·24”},{“Name”:“qiye”,“Age”:24}和{“name”:“qiye”,“age”:“24”}都是不同的。

集合: 集合在MongoDB中是一组文档,类似关系型数据库中的数据表。集合存在于数据库中,集合没有固定的结构,这意味着你在集合中可以插入不同格式和类型的数据,比如{“name”:“qiye”,“age”:19}、{“name”:“admin”,“age”:22,“sex”:“1”},可以存在同一个集合当中。合法的集合名为:

·集合名不能是空字符串。

·集合名不能含有“\0”字符(空字符),这个字符表示集合名的结尾。

·集合名不能以“system.”开头,这是为系统集合保留的前缀。

·用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含保留字符,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现“$”。

数据库: 一个MongoDB中可以建立多个数据库,默认数据库为“db”,该数据库存储在data目录中,这就是我们当时为什么在data目录下创建db文件夹。MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。在MongoDB的shell窗口中,使用show dbs命令可以查看所有的数据库,使用db命令可以看当前的数据库。

2.MongoDB常见数据类型

MongoDB中常用的几种数据类型如表8-12所示。

表8-12 MongoDB中常用的几种数据类型

3.创建/删除数据库

MongoDB创建数据库的语法格式如下:use DATABASE_NAME。如果数据库不存在,则创建数据库,否则切换到指定数据库。如果你想查看所有数据库,可以使用show dbs命令,但是数据库中如果没有数据,就显示不出来。

MongoDB删除数据库的语法格式如下:db.dropDatabase()。此语句可以删除当前数据库,你可以使用db命令查看当前数据库名。

下面在MongoDB的shell中新建一个名称为pythonSpider的数据库,接着再删除,如图8-19所示。

图8-19 创建/删除数据库

4.集合中文档的增删改查

上面我们已经创建了一个pythonSpider数据库,以下均是在这个数据库中进行操作。文档的数据结构和JSON基本一样,所有存储在集合中的数据都是BSON格式,BSON是类JSON的一种二进制形式的存储格式。

插入文档 。MongoDB使用insert()或save()方法向集合中插入文档,语法如下:

  db.COLLECTION_NAME.insert(document)

示例如下:

  >db.python.insert({title: 'python',
     description: '动态语言',
     url: 'http://www.python.org',
     tags: ['动态', '编程', '脚本'],
     likes: 100
  })

以上示例中python是我们的集合名称,如果该集合不在该数据库中,MongoDB会自动创建该集合并插入文档。插入的数据必须符合JSON格式。

查询文档。 MongoDB使用find()方法从集合中查询文档。查询数据的语法格式如下:

  db.COLLECTION_NAME.find()

如果你需要以易读的方式来读取数据,可以使用pretty()方法,语法格式如下:

  db.COLLECTION_NAME.find().pretty()

示例如下:

  > db.python.find()

上面的代码用于查出python集合中的所有的文档,相当于select*ftom table。如果我们想进行条件操作,就需要了解一下MongoDB中的条件语句和操作符,如表8-13所示。

表8-13 MongoDB中的条件语句和操作符

表中的例子都是单条件操作,下面说一下条件组合,类似于and和or的功能。

MongoDB的find()方法可以传入多个键(key),每个键以逗号隔开,来实现AND条件。语法格式如下:

  >db. COLLECTION_NAME.find({key1:value1, key2:value2}).pretty()

查找python集合中likes大于等于100且title等于python的文档,示例如下:

  >db.python.find({"likes": {$gte:100}, "title":"python"}).pretty()

运行效果为:

  {
     "_id" : ObjectId("5833f31a386f0b6ffa7aedf4"),
     "title" : "python",
     "description" : "动态语言",
     "url" : "http://www.python.org",
     "tags" : [
            "动态",
            "编程",
            "脚本"
     ],
     "likes" : 100
  }

MongoDB OR条件语句使用了关键字“$or”,语法格式如下:

  >db.COLLECTION_NAME.find(
     {
       $or: [
        {key1: value1}, {key2:value2}
       ]
     }
  ).pretty()

查找python集合中likes大于等于100或者title等于python的文档,示例如下:

  > db. python.find(
     {
       $or: [
            {"likes": {$gte:100}}, {"title":"python"}
       ]
     }
  ).pretty()

MongoDB AND和OR条件可以联合使用,示例如下:

  >db.python.find({"likes": {$gt:50}, $or: [{"description ": "动态语言"},{"title": "python"}]}).pretty()

更新文档。 MongoDB使用update()和save()方法来更新集合中的文档。首先看一下update()方法,用于更新已经存在的文档,方法原型如下:

  db.collection.update(
     query,
     update,
     {
       upsert: boolean
       multi: boolean
       writeConcern: document
     }
  )

参数分析:

·query:update的查询条件,类似where子句。

·update:update的对象和一些更新的操作符等,类似于set后面的内容。

·upsert:可选,这个参数的意思是如果不存在update的记录,是否插入新的文档,true为插入,默认是false。

·multi:可选,mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。

·writeConcern:可选,抛出异常的级别。

我们将title为python的文档修改为title为“python”爬虫,示例如下:

  >db.python.update({'title':'python'},{$set:{'title':'python爬虫'}})

以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置multi参数为true。示例如下:

  >db.python.update({'title':'python'},{$set:{'title':'python爬虫'}},{multi:true})

save()方法通过传入的文档来替换已有文档。方法原型如下:

  db.collection.save(
     document,
     {
       writeConcern: document
     }
  )

参数说明:

·document:文档数据。

·writeConcern:可选,抛出异常的级别。

我们替换一下_id为5833f31a386f0b6ffa7aedf4的文档数据,示例如下:

  >db.python.save(
     {
       "_id" : ObjectId("5833f31a386f0b6ffa7aedf4"),
       "title" : "Mongodb",
       "description" : "数据库",
       "url" : "http://www.python.org",
       "tags" : [
              "分布式",
              "mongo"
       ],
       "likes" : 100
     }
  )

删除文档。 MongoDB提供了remove()方法来删除文档,函数原型如下:

  db.collection.remove(
     query,
     {
       justOne: boolean,
       writeConcern: document
     }
  )

参数说明:

·query:可选,删除的文档的条件。

·justOne:可选,如果设为true或1,则只删除一个文档。

·writeConcern:可选,抛出异常的级别。

将刚才更新的文档删除,也就是删除title等于MongoDB的文档,示例如下:

  >db.python.remove({'title':'Mongodb'})

如果没有query条件,意味着删除所有文档。

8.3.3 Python操作MongoDB

1.导入pymongo数据库模块

在导入pymongo之前,需要安装pymongo模块。使用pip安装,命令如下:

  pip install pymongo

安装成功后,导入pymongo模块:

  import pymongo

2.建立连接

pymongo模块使用MongoClient对象来描述一个数据库客户端,创建对象所需的参数主要是host和port。常见的有三种形式:

·client=pymongo.MongoClient()

·client=pymongo.MongoClient(’localhost‘,27017)

·client=pymongo.MongoClient(’mongodb://localhost:27017/‘)

第一种方式是连接默认的主机IP和端口,第二种显式指定IP和端口,第三种是采用URL格式进行连接。

3.获取数据库

一个MongoDB实例可以支持多个独立的数据库。使用pymongo时,可以通过访问MongoClient的属性的方式来访问数据库:

  db = client.papers

如果数据库名字导致属性访问方式不能用(比如pa-pers),可以通过字典的方式访问数据库:

  db = client['pa-pers']

4.获取一个集合

一个collection指一组存在于MongoDB中的文档,获取Collection方法与获取数据库方法一致:

  collection = db.books

或者使用字典方式:

  collection = db['books']

需要强调的一点是,MongoDB里的collection和数据库都是惰性创建的,之前我们提到的所有命令实际并没有对MongoDB Server进行任何操作。直到第一个文档插入后,才会创建,这就是为什么在不插入文档之前,使用show dbs查看不到之前创建的数据库。

5.插入文档

数据在MongoDB中是以JSON类文件的形式保存起来的。在PyMongo中用字典来代表文档,使用insert()方法插入文档,示例如下:

  book = {"author": "Mike",
   "text": "My first book!",
   "tags": ["爬虫", "python", "网络"],
  "date": datetime.datetime.utcnow()
   }
  book_id= collection .insert(book)

文件被插入之后,如果文件内没有_id这个键值,那么系统自动添加一个到文件里。这是一个特殊键值,它的值在整个collection里是唯一的。insert()返回这个文件的_id值。

除了单个文件插入,也可以通过给insert()方法传入可迭代的对象作为第一个参数,进行批量插入操作。这将会把迭代表中的每个文件插入,而且只向Server发送一条命令:

  books = [{"author": "Mike",
   "text": "My first book!",
   "tags": ["爬虫", "python", "网络"],
  "date": datetime.datetime.utcnow()
   },{"author": "qiye",
   "text": "My sec book!",
   "tags": ["hack", "python", "渗透"],
  "date": datetime.datetime.utcnow()
   }]
  books_id = collection.insert(books)

6.查询文档

MongoDB中最基本的查询就是find_one。这个函数返回一个符合查询的文件,或者在没有匹配的时候返回None。示例如下:

  collection.find_one()

返回结果是一个之前插入的符合条件的字典类型值。注意,返回的文件里已经有了_id这个键值,是数据库自动添加的。

find_one()还支持对特定元素进行匹配查询。例如筛选出author为qiye的文档,代码如下:

  collection.find_one({"author": "qiye"})

通过_id也可以进行查询,book_id就是返回的id对象,类型为ObjectId。示例如下:

  collection.find_one({'_id':ObjectId('58344fcc1123ea2e54cb2e0f')})

这个常用于Web应用,可以从URL抽取id,从数据库中进行查询。

如果想获取多个文档,可以使用find()方法。find()返回一个Cursor实例,通过它我们可以获取每个符合查询条件的文档。示例如下:

  for book in collection.find():
     print book

与使用find_one()时候相同,可以传入条件来限制查询结果。比如查询所有作者是qiye的书:

  for book in collection.find({"author": "qiye"}):
     print book

如果只想知道符合查询条件的文件有多少,可以用count()操作,而不必进行完整的查询。示例如下:

  collection.find({"author": "qiye"}).count()

7.修改文档

MongoDB可以使用update()和save()方法来更新文档,和之前在MongoDB shell中的操作类似。示例如下:

  collection.update({"author": "qiye"},{"$set":{"text":"python book"}})

8.删除文档

MongoDB使用remove()方法来删除文档。示例如下:

  collection.remove({"author": "qiye"})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文