python网络爬虫——下载缓存(数据库)

数据库缓存

介于磁盘缓存的限制,爬取到的数据量比较大,但又无任何复杂的连接,所以选用NoSQL数据库,这种数据库相比创痛的关系型数据库更容易扩展。
什么是NoSQL?
NoSQL全称Not Only SQL,与传统的关系型数据库不同,NoSQL数据库通常是无模式的,考虑了跨服务器无缝分片问题。有多种方式可以实现该目标,分别是列数据存储(HBase)、键值对存储(Redis)、面向文档的数据库(MongoDB)以及图型数据库(Neo4j)。
安装MongoDB
下载MongoDB
官网链接:https://www.mongodb.com/

解压
tar -zxvf mongodb-linux-x86_64-rhel70-4.0.1.tgz
创建目录并将解压好的目录移动到创建的目录
mv mongodb-linux-x86_64-rhel70-4.0.1 /usr/local/mongodb/

添加可执行文件到PATH路径

export PATH=/usr/local/mongodb/mongodb-linux-x86_64-rhel70-4.0.1/bin:$PATH

创建数据库目录
MongoDB的数据存储在data目录下的db目录中,/data/db是默认的启动数据库路径,需要手动创建

创建并设置路径

[root@foundation155 bin]# ./mongod -dbpath=/data/db

pip install pymongo

尝试链接

>>> from pymongo import MongoClient
>>> client=MongoClient('localhost',27017)

pymongo的基本用法

# coding:utf-8

from pymongo import MongoClient
import pymongo

#连接数据服务器,获取客户端信息
client=MongoClient('localhost',27017)

#获取myDB数据库对象
db=client.myDB

#获取对象集合
colletion=db.mycollection

tom={'name':'Tom','age':18,'sex':'男','hobbies':['吃饭','睡觉','打豆豆']}
alice={'name':'Alice','age':19,'sex':'女','hobbies':['读书','跑步','弹吉他']}


# #******************************************插入文档***********************************
#插入文档,返回一个ObjectID类型的_id属性
tom_id=colletion.insert(tom)
alice_id=colletion.insert(alice)

#也可以插入多条以列表形式
colletion.insert([tom,alice])
#返回的是InsertOneResult对象

#不过insert()已经不推荐使用了而使用insert_one()和insert_many()

print tom_id
# 5b757427c3cf5b37b403c9c8
print alice_id
# 5b757427c3cf5b37b403c9c9
#********************************查询文档*******************************

cursor=colletion.find()

#文档个数
print cursor.count()
# 4


# 查询name为Tom的文档
print colletion.find_one({'name':'Tom'})
# {u'age': 18, u'_id': ObjectId('5b7573edc3cf5b3784c43442'), u'sex':
#  u'\u7537', u'name': u'Tom', u'hobbies': [u'\u5403\u996d', u'\u7761\u89c9',
# u'\u6253\u8c46\u8c46']}

#返回一个字典,不过多了id,这是在插入过程中自动添加的,也可以通过这个_id查询
from bson.objectid import ObjectId

result=colletion.find_one({'_id':ObjectId('5b757a46c3cf5b3b573fd0af')})
print result
# {u'age': 19, u'_id': ObjectId('5b757a46c3cf5b3b573fd0af'), u'sex': u'\u5973', u'name': u'Alice', u'hobbies': [u'\u8bfb\u4e66', u'\u8dd1\u6b65', u'\u5f39\u5409\u4ed6']}


#查询多条
#查询年龄为18的
results=colletion.find({'age':19})
print results
# # <pymongo.cursor.Cursor object at 0x7f79cd868e90>
# # 返回一个游标对象,相当于一个生成器
#
for result in results:
    print result
# {u'age': 19, u'_id': ObjectId('5b757a46c3cf5b3b573fd0af'), u'sex': u'\u5973', u'name': u'Alice', u'hobbies': [u'\u8bfb\u4e66', u'\u8dd1\u6b65', u'\u5f39\u5409\u4ed6']}


#查询年龄大与17的
results=colletion.find({'age':{'$gt':17}})
print [result for result in results]
# [{u'age': 18, u'_id': ObjectId('5b757a46c3cf5b3b573fd0ae'), u'sex': u'\u7537', u'name': u'Tom', u'hobbies': [u'\u5403\u996d', u'\u7761\u89c9', u'\u6253\u8c46\u8c46']},
#  {u'age': 19, u'_id': ObjectId('5b757a46c3cf5b3b573fd0af'), u'sex': u'\u5973', u'name': u'Alice', u'hobbies': [u'\u8bfb\u4e66', u'\u8dd1\u6b65', u'\u5f39\u5409\u4ed6']}]


#比较字符
"""
$lt小于;
$gt大于;
$lte小于等于
$gte大于等于
$ne不等于
$in在范围内{'age':{$in:[20,30]}}
$nin不再范围内
"""

#使用正则匹配
#查询名字里含有m的文档
results=colletion.find({'name':{'$regex':'m'}})
for i in results:
    print i
# {u'age': 18, u'_id': ObjectId('5b757a46c3cf5b3b573fd0ae'), u'sex': u'\u7537', u'name': u'Tom', u'hobbies': [u'\u5403\u996d', u'\u7761\u89c9', u'\u6253\u8c46\u8c46']}

# 符号含义表示
"""
$regex匹配正则{'name':{'$regex':'^M.*'}}name以M开头
$exists属性是否存在{'name':{'$exists':True}name属性是否存在
$type类型判断{'age':{'$type':''int}}
$mod数字模操作{'age':{'$mod':[5,0]}}年龄模5余0
$text文本查询{'$text':{'$search':'Mike'}}text类型的属性中包含MIike字符串
$where高级条件查询{'$where':'condition'}
"""

#符合某个条件数据的条数
colletion.find().count()

#排序
#传入排序的字段及升降序的标志
results=colletion.find().sort('name',pymongo.ASCENDING)
print ([result['name'] for  result in results])


#还可以指定偏移几个位置
results=colletion.find().sort('name',pymongo.ASCENDING).skip(2)

#指定获取结果的数量
results=colletion.find().sort('name',pymongo.ASCENDING).skip(2).limit(2)


#******************************************更新****************************
condition={'name':'Tom'}

student=colletion.find_one(condition)
student['age']=20
result=colletion.update(condition,student)
print result
# {'updatedExisting': True, u'nModified': 1, u'ok': 1.0, u'n': 1}
# ok代表执行成功,nModified代表影响数据的条数


condition={'name':'Alice'}
student=colletion.find_one(condition)
student['age']=26
result=colletion.update_one(condition,{'$set':student})
print result
# <pymongo.results.UpdateResult object at 0x7fcc5af68098>

print (result.matched_count,result.modified_count)
# 匹配的条数,影响的条数
# (1, 0)


condition={'age':{'$gt':20}}
#匹配条件年龄大于20,更新后给所有数据的年龄加1
results=colletion.update_many(condition,{'$inc':{'age':1}})
print result
print (result.matched_count,result.modified_count)
# <pymongo.results.UpdateResult object at 0x7f24204dc0e0>
# (1, 1)

# *******************************************删除数据********************
result=colletion.remove({'name':'Tom'})
print result
# {u'ok': 1.0, u'n': 1}
#ok表示删除成功,n代表影响条数

#也支持delete_one()和delete_many()
result = colletion.delete_one({'name': 'Alice'})
print(result)
print(result.deleted_count)
result = colletion.delete_many({'age': {'$lt': 25}})
print(result.deleted_count)

实现

# coding:utf-8
import pickle
from datetime import timedelta, datetime
import zlib
from bson.binary import Binary
from pymongo import MongoClient

from Link_crawler import link_crawler


class MongoCache:

    def __init__(self,client=None,expires=timedelta(days=30)):
        """
        client:数据库客户端
        expires:文件有效期
        """
        self.client=MongoClient('localhost',27017) if client is None else client
        #获取数据库对象
        self.db=self.client.cache
        #获取集合文档
        self.db.webpage.create_index('timestamp',expireAfterSeconds=expires.total_seconds())

    def __contains__(self, url):

        try:
            self[url]
        except KeyError:
            return False
        else:
            return True


    def __getitem__(self, url):
        """加载这个URL的数据"""

        record=self.db.webpage.find_one({'_id':url})
        if record:
            #pickle.loads将获取到的数据存入内存,以便访问
            #zlib.decompress解压数据
            return pickle.loads(zlib.decompress(record['result']))
        else:
            raise KeyError(url+'does not exist')

    def __setitem__(self,url,result):
        """将数据存入数据库"""
        # Binary转换为二进制形式
        # pickle.dumps从内存重读取
        # zlib.compress压缩数据
        #将数据和目前的时间创建一个字典
        record={'result':Binary(zlib.compress(pickle.dumps(result))),'timestamp':datetime.utcnow()}
        # 将数据更新到数据库
        self.db.webpage.update({'_id':url},{'$set':record},upsert=True)

    def clear(self):
        self.db.webpage.drop()



if __name__=='__main__':
    import time
    start=time.time()
    link_crawler('http://example.webscraping.com/', '/view', cache=MongoClient())
    print "runing:%s" %(time.time()-start)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值