1. 程式人生 > >Python爬蟲實戰完整版

Python爬蟲實戰完整版

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,反正閒著也是閒著呢,不如學點東西啦~~