8.3 更适合爬虫的 MongoDB
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论