Python爬蟲實戰完整版
阿新 • • 發佈:2018-12-12
mongodb操作
有需要Python學習資料的小夥伴嗎?小編整理【一套Python資料、原始碼和PDF】,感興趣者可以加學習群:548377875,反正閒著也是閒著呢,不如學點東西啦~~
import pymongo #連線資料庫例項(連線資料庫)---》獲取相應資料庫---》獲取相應collection集合(表) client = pymongo.MongoClient(host='localhost',port=27017) db = client.test #也可用字典形式操作,如下 # db = client["test"] collection = db.students #也可用字典形式操作,如下 # collection = db["students"] student1 = { 'id':'001', 'name':'haha', 'age':20, 'gender':'male' } student2 = { 'id': '002', 'name': 'Mike', 'age': 41, 'gender': 'male' } #-------------------------------------------------------------------------- #插入 insert into students(...) values('002',...) #若不指定 _id 欄位,系統預設會生成一個ObjectId #可插入一條或多條資料(列表形式),python3不推薦使用insert # collection.insert([student1,student2]) # collection.insert(student1) #官方推薦,分開使用,返回值不是ObjectId,而是InsertOneResult物件,我們可以呼叫其inserted_id屬性獲取_id。 # result = collection.insert_one(student2) # print(result) # print(result.inserted_id) # result = collection.insert_many([student1,student2]) # print(result) # print(result.inserted_ids) #------------------------------------------------------------------ #查詢 select * from students where id=002 #查詢條件使用字典,可使用多欄位,find是多條查詢 # result_find = collection.find({"name":"lijingbo","age":20}) # print(result_find.next()) #返回一個遊標,遊標相當於迭代器,可使用next()獲取一條結果,或者使用迴圈遍歷等,遍歷結果是字典 #find_one:單個查詢,返回字典型別 # result = collection.find_one({'age':20}) # print(result,type(result)) #結合關係符進行查詢:$gt,$lt,$gte,$lte,$ne,$in,$nin # result = collection.find({'age':{'$gt':18}}) # result = collection.find({'age':{'$in':[18,41]}}) #結合特殊符號查詢:$regex # result = collection.find({'name':{'$regex':'^M.*'}}) #正則 # result = collection.find({'name':{'$exists':True}}) #查詢含有name屬性的 # result = collection.find({'age':{'$mod':[5,0]}}) #求模,對5取餘=0 # result = collection.find({'$where':'obj.age==20'}) #查詢age為20的,obj是自身 # result = collection.find({'age':20}).count() #統計 # result = collection.find().sort('age',pymongo.ASCENDING) #按照指定欄位升序排列 # result = collection.find().sort('age',pymongo.DESCENDING) #按照指定欄位升序排列 # result = collection.find().sort('age',pymongo.DESCENDING).skip(2) #按照指定欄位升序排列,偏移2個(就是把最前面兩個跳過去了) # result = collection.find().sort('age',pymongo.DESCENDING).skip(2).limit(5) #限制得到5 # print(result) # for r in result: # print(r['name'],r['age']) #---------------------------------------------------------- #更新 update students set name=haha where id=001 #引數1:查詢條件(字典);引數2:更新值(字典,鍵:'$set',值:字典【也可直接使用外部字典】) #其他:upsert預設為False,為True時——若更新的原資料不存在,則插入資料 #multi——預設為False只更新查詢到的第一條資料,為True時:更新全部查詢到的資料 # $set:是mongodb內建函式,覆蓋原始資料 # collection.update({"id":"001"},{'$set':{'age':34}},upsert=True,multi=True) # print(collection.find().next()) #上面的官方也不推薦,可以使用下面的 # result = collection.update_one({'name':'haha'},{'$set':{'age':18}}) # result = collection.update_many({'name':'haha'},{'$set':{'age':18}}) # print(result) #只修改一條資料,若該資料不修改就和修改條件一樣了,那有可能修改數為0 # print(result.matched_count,result.modified_count) #----------------------------------------------------- #刪除,remove方法官方不推薦 # collection.remove({"id":"001"},justOne=1) # result = collection.delete_one({'name':'Mike'}) # result = collection.delete_many({'name':'Mike'}) # print(result) # print(result.deleted_count) #--------------------------------------------------- #組合方法 # result = collection.find_one_and_delete({'name':'haha'}) # result = collection.find_one_and_update({'name':'haha'},{'$set':{'age':45}}) # result = collection.find_one_and_replace({'name':'haha'}) # print(result)
MongoCache
將資料以字典的特性儲存快取到mongodb資料庫
匯入類庫
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
- 清空該集合中的資料
import pickle,zlib #物件序列化 壓縮資料
from datetime import datetime,timedelta #設定快取超時間間隔
from pymongo import MongoClient
from bson.binary import Binary #MongoDB儲存二進位制的型別
from http_ljb.tiebaspider import TiebaSpider
from http_ljb.qiushispider import QiushiSpider
class MongoCache:
def __init__(self,client=None,expires=timedelta(days=30)):
'''
初始化函式
:param client: 資料庫連線(資料庫例項)
:param expires: 超時時間
'''
self.client = MongoClient('localhost',27017)
self.db = self.client.cache #建立名為cache的資料庫
web_page = self.db.webpage #建立集合webpage並賦值給變數
#建立timestamp索引,設定超時時間為30天,total_seconds會將days轉為秒
self.db.webpage.create_index('timestamp',expireAfterSeconds=expires.total_seconds())
def __setitem__(self, key, value):
'''
用字典的形式向資料庫新增一條快取(資料)
:param key: 快取的鍵
:param value: 快取的值
:return:
'''
#資料---》pickle序列化---》zlib壓縮---》Binary轉化為mondodb需要的格式,使用格林威治時間
record = {'result':Binary(zlib.compress(pickle.dumps(value))),'timestamp':datetime.utcnow()}
#使用下載的url(路由)作為key,存入系統預設的_id欄位,更新資料庫,若存在則更新,不存在則插入,_id唯一就可實現爬取的資料去重
self.db.webpage.update({'_id':key},{'$set':record},upsert=True)
def __getitem__(self, item):
'''
將快取資料按照item作為key取出(key仍然是下載的url)
:param item:鍵
:return:
'''
record = self.db.webpage.find_one({'_id':item}) #查找出來就不是Binary了,不用進行轉化
if record:
return pickle.loads(zlib.decompress(record['result'])) #解壓縮,反序列化
else:
raise KeyError(item + 'does not exist') #查詢不到就丟擲鍵錯誤異常
def __contains__(self, item):
'''
當呼叫in,not in ,會自動呼叫該方法判斷連結對應網址是否在資料庫中
:param item: 下載的url連結(路由)
:return:
'''
try:
self[item] #這一步會呼叫__getitem__,找不到__getitem__會丟擲異常,在這裡進行捕獲異常只返回False,否則返回True
except KeyError:
return False
else:
return True
def clear(self):
'''
清空該集合中的資料
:return:
'''
self.db.webpage.drop()
爬取例項
呼叫貼吧爬取程式碼和百科爬取程式碼,使用mongodb儲存爬取資料
- 匯入爬取類
- 建立新類並繼承自爬取類
- 重寫儲存方法
- 建立MongoCache物件
- 網址為鍵,資料為值,以字典形式存入mongodb
- 重寫run方法
- 在儲存時,需多傳一個網址引數(為了在儲存方法中對應儲存)
import pickle,zlib #物件序列化 壓縮資料
from datetime import datetime,timedelta #設定快取超時間間隔
from pymongo import MongoClient
from bson.binary import Binary #MongoDB儲存二進位制的型別
from http_ljb.tiebaspider import TiebaSpider
from http_ljb.qiushispider import QiushiSpider
class MongoCache:
def __init__(self,client=None,expires=timedelta(days=30)):
'''
初始化函式
:param client: 資料庫連線(資料庫例項)
:param expires: 超時時間
'''
self.client = MongoClient('localhost',27017)
self.db = self.client.cache #建立名為cache的資料庫
web_page = self.db.webpage #建立集合webpage並賦值給變數
#建立timestamp索引,設定超時時間為30天,total_seconds會將days轉為秒
self.db.webpage.create_index('timestamp',expireAfterSeconds=expires.total_seconds())
def __setitem__(self, key, value):
'''
用字典的形式向資料庫新增一條快取(資料)
:param key: 快取的鍵
:param value: 快取的值
:return:
'''
#資料---》pickle序列化---》zlib壓縮---》Binary轉化為mondodb需要的格式,使用格林威治時間
record = {'result':Binary(zlib.compress(pickle.dumps(value))),'timestamp':datetime.utcnow()}
#使用下載的url(路由)作為key,存入系統預設的_id欄位,更新資料庫,若存在則更新,不存在則插入,_id唯一就可實現爬取的資料去重
self.db.webpage.update({'_id':key},{'$set':record},upsert=True)
def __getitem__(self, item):
'''
將快取資料按照item作為key取出(key仍然是下載的url)
:param item:鍵
:return:
'''
record = self.db.webpage.find_one({'_id':item}) #查找出來就不是Binary了,不用進行轉化
if record:
return pickle.loads(zlib.decompress(record['result'])) #解壓縮,反序列化
else:
raise KeyError(item + 'does not exist') #查詢不到就丟擲鍵錯誤異常
def __contains__(self, item):
'''
當呼叫in,not in ,會自動呼叫該方法判斷連結對應網址是否在資料庫中
:param item: 下載的url連結(路由)
:return:
'''
try:
self[item] #這一步會呼叫__getitem__,找不到__getitem__會丟擲異常,在這裡進行捕獲異常只返回False,否則返回True
except KeyError:
return False
else:
return True
def clear(self):
'''
清空該集合中的資料
:return:
'''
self.db.webpage.drop()
class TiebaMongo(TiebaSpider):
def save_result(self, result,url_str):
"""
重寫父類的該方法,將資料儲存到資料庫
:param result:
:param url_str:
:return:
"""
mc = MongoCache()
mc[url_str] = result
def run(self):
url_lists = self.make_url()
for url_str in url_lists:
result_str = self.download_url(url_str)
self.save_result(result=result_str,url_str=url_str)
# class QiushiMongo(QiushiSpider):
# def save_result(self, result,url_str):
# mc = MongoCache()
# mc[url_str] = result
#
# def run(self):
# url_lists = self.make_url()
# for url_str in url_lists:
# result_str = self.download_url(url_str)
# self.save_result(result=result_str,url_str=url_str)
# if __name__ == '__main__':
#爬取貼吧並存到MongoDB
# test = TiebaMongo('lol')
# test.run()
#爬取糗事並存到MongoDB
# qiushi = QiushiMongo()
# qiushi.run()
#查詢MongoDB
# mc = MongoCache()
# print(mc['https://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=2'])
# print('https://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=3' in mc)
# cha = MongoCache()
# print(cha[test.url_base])
# print(mc["https://www.qiushibaike.com/8hr/page/2/"])
有需要Python學習資料的小夥伴嗎?小編整理【一套Python資料、原始碼和PDF】,感興趣者可以加學習群:548377875,反正閒著也是閒著呢,不如學點東西啦~~