前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫——实战完整版

爬虫——实战完整版

作者头像
py3study
发布2020-01-19 11:49:05
1.2K0
发布2020-01-19 11:49:05
举报
文章被收录于专栏:python3python3

mongodb操作

代码语言:javascript
复制
 1 import pymongo
 2 
 3 #连接数据库实例(连接数据库)---》获取相应数据库---》获取相应collection集合(表)
 4 client = pymongo.MongoClient(host='localhost',port=27017)
 5 
 6 db = client.test        #也可用字典形式操作,如下
 7 # db = client["test"]
 8 
 9 collection  = db.students  #也可用字典形式操作,如下
10 # collection = db["students"]
11 
12 student1 = {
13     'id':'001',
14     'name':'haha',
15     'age':20,
16     'gender':'male'
17 }
18 student2 = {
19     'id': '002',
20     'name': 'Mike',
21     'age': 41,
22     'gender': 'male'
23 }
24 #--------------------------------------------------------------------------
25         #插入 insert into students(...) values('002',...)
26         #若不指定 _id 字段,系统默认会生成一个ObjectId
27         #可插入一条或多条数据(列表形式),python3不推荐使用insert
28 # collection.insert([student1,student2])
29 # collection.insert(student1)
30 
31         #官方推荐,分开使用,返回值不是ObjectId,而是InsertOneResult对象,我们可以调用其inserted_id属性获取_id。
32 # result = collection.insert_one(student2)
33 # print(result)
34 # print(result.inserted_id)
35 
36 # result = collection.insert_many([student1,student2])
37 # print(result)
38 # print(result.inserted_ids)
39 
40 #------------------------------------------------------------------
41         #查询 select * from students where id=002
42         #查询条件使用字典,可使用多字段,find是多条查询
43 # result_find = collection.find({"name":"lijingbo","age":20})
44 # print(result_find.next())   #返回一个游标,游标相当于迭代器,可使用next()获取一条结果,或者使用循环遍历等,遍历结果是字典
45         #find_one:单个查询,返回字典类型
46 # result = collection.find_one({'age':20})
47 # print(result,type(result))
48         #结合关系符进行查询:$gt,$lt,$gte,$lte,$ne,$in,$nin
49 # result = collection.find({'age':{'$gt':18}})
50 # result = collection.find({'age':{'$in':[18,41]}})
51         #结合特殊符号查询:$regex
52 # result = collection.find({'name':{'$regex':'^M.*'}})  #正则
53 # result = collection.find({'name':{'$exists':True}})     #查询含有name属性的
54 # result = collection.find({'age':{'$mod':[5,0]}})        #求模,对5取余=0
55 # result = collection.find({'$where':'obj.age==20'})       #查询age为20的,obj是自身
56 # result = collection.find({'age':20}).count()                #统计
57 # result = collection.find().sort('age',pymongo.ASCENDING)      #按照指定字段升序排列
58 # result = collection.find().sort('age',pymongo.DESCENDING)     #按照指定字段升序排列
59 # result = collection.find().sort('age',pymongo.DESCENDING).skip(2)     #按照指定字段升序排列,偏移2个(就是把最前面两个跳过去了)
60 # result = collection.find().sort('age',pymongo.DESCENDING).skip(2).limit(5)    #限制得到5
61 # print(result)
62 # for r in result:
63 #     print(r['name'],r['age'])
64 
65 #----------------------------------------------------------
66         #更新 update students set name=haha where id=001
67         #参数1:查询条件(字典);参数2:更新值(字典,键:'$set',值:字典【也可直接使用外部字典】)
68         #其他:upsert默认为False,为True时——若更新的原数据不存在,则插入数据
69                 #multi——默认为False只更新查询到的第一条数据,为True时:更新全部查询到的数据
70         # $set:是mongodb内置函数,覆盖原始数据
71 # collection.update({"id":"001"},{'$set':{'age':34}},upsert=True,multi=True)
72 # print(collection.find().next())
73         #上面的官方也不推荐,可以使用下面的
74 # result = collection.update_one({'name':'haha'},{'$set':{'age':18}})
75 # result = collection.update_many({'name':'haha'},{'$set':{'age':18}})
76 # print(result)   #只修改一条数据,若该数据不修改就和修改条件一样了,那有可能修改数为0
77 # print(result.matched_count,result.modified_count)
78 
79 
80 #-----------------------------------------------------
81         #删除,remove方法官方不推荐
82 # collection.remove({"id":"001"},justOne=1)
83 # result = collection.delete_one({'name':'Mike'})
84 # result = collection.delete_many({'name':'Mike'})
85 # print(result)
86 # print(result.deleted_count)
87 
88 #---------------------------------------------------
89         #组合方法
90 # result = collection.find_one_and_delete({'name':'haha'})
91 # result = collection.find_one_and_update({'name':'haha'},{'$set':{'age':45}})
92 # result = collection.find_one_and_replace({'name':'haha'})
93 # print(result)

MongoCache

将数据以字典的特性存储缓存到mongodb数据库

导入类库

代码语言:javascript
复制
import pickle,zlib  #对象序列化    压缩数据
from datetime import datetime,timedelta     #设置缓存超时间间隔
from pymongo import MongoClient
from bson.binary import Binary      #MongoDB存储二进制的类型

创建MongoCache类

  • 初始化init
    • 连接mongodb数据库
    • 连接数据库cache实例(没有则创建)
    • 连接集合webpage(没有则创建)
    • 创建timestamp索引,设置超时时间为30天
  • 重写__setitem__
    • 数据经过pickle序列化
    • zlib压缩
    • 经Binary转化为mongodb需要的格式
    • 添加格林威治时间
    • 网址为键_id,结果为值,存入mongodb

使用下载的url(路由)作为key,存入系统默认的_id字段,更新数据库,若存在则更新,不存在则插入,_id唯一就可实现爬取的数据去重

用字典的形式向数据库添加一条缓存(数据)

  • 重写__getitem__
    • 将缓存数据按照item作为key取出(key仍然是下载的url)
    • 根据_id(url)查找(find_one)结果
    • 解压缩,反序列化
  • 重写__contains__
    • 当调用in,not in ,会自动调用该方法判断链接对应网址是否在数据库中
    • 可通过字典的查找方式__getitem__直接查找(self[item])
    • 该函数返回布尔值
  • 方法clear
    • 清空该集合中的数据
代码语言:javascript
复制
1 import pickle,zlib  #对象序列化    压缩数据
 2 from datetime import datetime,timedelta     #设置缓存超时间间隔
 3 from pymongo import MongoClient
 4 from bson.binary import Binary      #MongoDB存储二进制的类型
 5 from http_ljb.tiebaspider import TiebaSpider
 6 from http_ljb.qiushispider import QiushiSpider
 7 
 8 class MongoCache:
 9     def __init__(self,client=None,expires=timedelta(days=30)):
10         '''
11         初始化函数
12         :param client: 数据库连接(数据库实例)
13         :param expires: 超时时间
14         '''
15         self.client = MongoClient('localhost',27017)
16         self.db = self.client.cache     #创建名为cache的数据库
17         web_page = self.db.webpage      #创建集合webpage并赋值给变量
18         #创建timestamp索引,设置超时时间为30天,total_seconds会将days转为秒
19         self.db.webpage.create_index('timestamp',expireAfterSeconds=expires.total_seconds())
20 
21     def __setitem__(self, key, value):
22         '''
23         用字典的形式向数据库添加一条缓存(数据)
24         :param key: 缓存的键
25         :param value: 缓存的值
26         :return:
27         '''
28         #数据---》pickle序列化---》zlib压缩---》Binary转化为mondodb需要的格式,使用格林威治时间
29         record = {'result':Binary(zlib.compress(pickle.dumps(value))),'timestamp':datetime.utcnow()}
30         #使用下载的url(路由)作为key,存入系统默认的_id字段,更新数据库,若存在则更新,不存在则插入,_id唯一就可实现爬取的数据去重
31         self.db.webpage.update({'_id':key},{'$set':record},upsert=True)
32 
33     def __getitem__(self, item):
34         '''
35         将缓存数据按照item作为key取出(key仍然是下载的url)
36         :param item:键
37         :return:
38         '''
39         record = self.db.webpage.find_one({'_id':item}) #查找出来就不是Binary了,不用进行转化
40         if record:
41             return pickle.loads(zlib.decompress(record['result'])) #解压缩,反序列化
42         else:
43             raise KeyError(item + 'does not exist')     #查询不到就抛出键错误异常
44 
45     def __contains__(self, item):
46         '''
47         当调用in,not in ,会自动调用该方法判断链接对应网址是否在数据库中
48         :param item: 下载的url链接(路由)
49         :return:
50         '''
51         try:
52             self[item]      #这一步会调用__getitem__,找不到__getitem__会抛出异常,在这里进行捕获异常只返回False,否则返回True
53         except KeyError:
54             return False
55         else:
56             return True
57 
58     def clear(self):
59         '''
60         清空该集合中的数据
61         :return:
62         '''
63         self.db.webpage.drop()
 
 

爬取实例

调用贴吧爬取代码和百科爬取代码,使用mongodb存储爬取数据

  • 导入爬取类
  • 创建新类并继承自爬取类
  • 重写保存方法
    • 创建MongoCache对象
    • 网址为键,数据为值,以字典形式存入mongodb
  • 重写run方法
    • 在保存时,需多传一个网址参数(为了在保存方法中对应保存)
代码语言:javascript
复制
 1 import pickle,zlib  #对象序列化    压缩数据
  2 from datetime import datetime,timedelta     #设置缓存超时间间隔
  3 from pymongo import MongoClient
  4 from bson.binary import Binary      #MongoDB存储二进制的类型
  5 from http_ljb.tiebaspider import TiebaSpider
  6 from http_ljb.qiushispider import QiushiSpider
  7 
  8 class MongoCache:
  9     def __init__(self,client=None,expires=timedelta(days=30)):
 10         '''
 11         初始化函数
 12         :param client: 数据库连接(数据库实例)
 13         :param expires: 超时时间
 14         '''
 15         self.client = MongoClient('localhost',27017)
 16         self.db = self.client.cache     #创建名为cache的数据库
 17         web_page = self.db.webpage      #创建集合webpage并赋值给变量
 18         #创建timestamp索引,设置超时时间为30天,total_seconds会将days转为秒
 19         self.db.webpage.create_index('timestamp',expireAfterSeconds=expires.total_seconds())
 20 
 21     def __setitem__(self, key, value):
 22         '''
 23         用字典的形式向数据库添加一条缓存(数据)
 24         :param key: 缓存的键
 25         :param value: 缓存的值
 26         :return:
 27         '''
 28         #数据---》pickle序列化---》zlib压缩---》Binary转化为mondodb需要的格式,使用格林威治时间
 29         record = {'result':Binary(zlib.compress(pickle.dumps(value))),'timestamp':datetime.utcnow()}
 30         #使用下载的url(路由)作为key,存入系统默认的_id字段,更新数据库,若存在则更新,不存在则插入,_id唯一就可实现爬取的数据去重
 31         self.db.webpage.update({'_id':key},{'$set':record},upsert=True)
 32 
 33     def __getitem__(self, item):
 34         '''
 35         将缓存数据按照item作为key取出(key仍然是下载的url)
 36         :param item:键
 37         :return:
 38         '''
 39         record = self.db.webpage.find_one({'_id':item}) #查找出来就不是Binary了,不用进行转化
 40         if record:
 41             return pickle.loads(zlib.decompress(record['result'])) #解压缩,反序列化
 42         else:
 43             raise KeyError(item + 'does not exist')     #查询不到就抛出键错误异常
 44 
 45     def __contains__(self, item):
 46         '''
 47         当调用in,not in ,会自动调用该方法判断链接对应网址是否在数据库中
 48         :param item: 下载的url链接(路由)
 49         :return:
 50         '''
 51         try:
 52             self[item]      #这一步会调用__getitem__,找不到__getitem__会抛出异常,在这里进行捕获异常只返回False,否则返回True
 53         except KeyError:
 54             return False
 55         else:
 56             return True
 57 
 58     def clear(self):
 59         '''
 60         清空该集合中的数据
 61         :return:
 62         '''
 63         self.db.webpage.drop()
 64 
 65 class TiebaMongo(TiebaSpider):
 66     def save_result(self, result,url_str):
 67         """
 68         重写父类的该方法,将数据保存到数据库
 69         :param result:
 70         :param url_str:
 71         :return:
 72         """
 73         mc = MongoCache()
 74         mc[url_str] = result
 75 
 76     def run(self):
 77         url_lists = self.make_url()
 78         for url_str in url_lists:
 79             result_str = self.download_url(url_str)
 80             self.save_result(result=result_str,url_str=url_str)
 81 
 82 # class QiushiMongo(QiushiSpider):
 83 #     def save_result(self, result,url_str):
 84 #         mc = MongoCache()
 85 #         mc[url_str] = result
 86 #
 87 #     def run(self):
 88 #         url_lists = self.make_url()
 89 #         for url_str in url_lists:
 90 #             result_str = self.download_url(url_str)
 91 #             self.save_result(result=result_str,url_str=url_str)
 92 
 93 # if __name__ == '__main__':
 94         #爬取贴吧并存到MongoDB
 95     # test = TiebaMongo('lol')
 96     # test.run()
 97         #爬取糗事并存到MongoDB
 98     # qiushi = QiushiMongo()
 99     # qiushi.run()
100         #查询MongoDB
101     # mc = MongoCache()
102     # print(mc['https://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=2'])
103     # print('https://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=3' in mc)
104     # cha = MongoCache()
105     # print(cha[test.url_base])
106     # print(mc["https://www.qiushibaike.com/8hr/page/2/"])
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-03-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • mongodb操作
  • MongoCache
    • 导入类库
      • 创建MongoCache类
      • 爬取实例
      相关产品与服务
      云数据库 MongoDB
      腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档