數(shù)據(jù)庫模塊-Python爬蟲之構(gòu)建代理池(一)

之前(Python爬蟲之構(gòu)建代理池)我們已經(jīng)說過將代理數(shù)據(jù)使用Redis進(jìn)行存儲管理甸怕,我們需要一個數(shù)據(jù)庫模塊來和Redis進(jìn)行交互操作,管理代理池中的代理梢杭。如果你還沒有做好準(zhǔn)備工作秸滴,請先移步Python爬蟲之構(gòu)建代理池

設(shè)計(jì)思路

我們的代理池中存儲著大量的代理吝羞,這些代理質(zhì)量性參差不齊,有的代理可能一開始可以用钧排,后來卻不可用了均澳。我們從代理池中獲取代理時,應(yīng)該優(yōu)先返回那些可用性高的代理找前,其次,對于長期不可用的代理项戴,應(yīng)該將其從代理池中清除槽惫。
所以我們可以給代理進(jìn)行評分辩撑,可用性越高的代理仿耽,評分越高,對于評分低于某一標(biāo)準(zhǔn)的代理進(jìn)行刪除君躺,我們可以這樣設(shè)計(jì):

  • 代理的最高評分我們設(shè)置為100开缎,100代表穩(wěn)定可用的代理。
  • 當(dāng)代理初次被加入代理池時谍珊,我們給的初始評分60。
  • 如果代理在一次檢測中可用,立馬將代理分?jǐn)?shù)置于100侮邀。
  • 如果代理在一次檢測中不可用,將代理的分?jǐn)?shù)減1铝宵,當(dāng)代理分?jǐn)?shù)小于50時华畏,將代理刪除。

Tip:這個分?jǐn)?shù)標(biāo)準(zhǔn)可以自己進(jìn)行設(shè)定侣夷。

開發(fā)

MyProxyPool項(xiàng)目中新建redisdb.py

import redis
from random import choice
import re

# ============= 分?jǐn)?shù)配置 =================
# 最大分?jǐn)?shù)
MAX_SCORE = 100
# 最小分?jǐn)?shù)
MIN_SCORE = 50
# 初始分?jǐn)?shù)
INIT_SCORE = 60

# ============= redis配置 =================
# 主機(jī)
REDIS_HOST = 'localhost'
# 端口
REDIS_PORT = 6379
# 密碼
REDIS_PASSWORD = None
# 鍵
REDIS_KEY = 'proxies'


class RedisCli:
    def __init__(self, host=REDIS_HOST, port = REDIS_PORT, password = REDIS_PASSWORD):
        '''
        初始化
        :param host: redis地址
        :param port: redis端口
        :param password: redis密碼
        '''
        self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)

    def add(self, proxy, score=INIT_SCORE):
        '''
        添加代理仑乌,設(shè)置默認(rèn)分?jǐn)?shù)
        :param proxy: 代理
        :param score: 分?jǐn)?shù)
        :return: 添加結(jié)果
        '''
        # 正則匹配代理格式是否正確
        if not re.match(r'\d+.\d+.\d+.\d+:\d+', proxy):
            print('代理 %s 無效 ==> 丟棄' % proxy)
            return
        # 判斷代理池中是否已經(jīng)存在
        if not self.db.zscore(REDIS_KEY, proxy):
            # 添加代理
            print('新增代理 %s ' % proxy)
            return self.db.zadd(REDIS_KEY, score, proxy)

    def random(self):
        '''
        隨機(jī)獲取有效代理
        :return: 隨機(jī)代理
        '''
        # 嘗試獲取最高分?jǐn)?shù)的代理集合
        result = self.db.zrangebyscore(REDIS_KEY,MAX_SCORE,MAX_SCORE)
        if len(result):
            # 如果有最高分?jǐn)?shù)的代理晰甚,隨機(jī)選擇返回
            return choice(result)
        else:
            # 獲取分?jǐn)?shù)排名前一百的代理
            result = self.db.zrevrange(REDIS_KEY, 0, 100)
            if len(result):
                # 如果有,隨機(jī)返回
                return choice(result)
            else:
                return None

    def decrease(self, proxy):
        '''
        將代理值減一分蓖捶,分?jǐn)?shù)小于最小值時扁远,移除代理俊鱼。
        :param proxy: 代理
        :return: 修改后的代理分?jǐn)?shù)
        '''
        score = self.db.zscore(REDIS_KEY, proxy)
        if score and score > MIN_SCORE:
            # 如果分?jǐn)?shù)大于最低分刻像,將分?jǐn)?shù)減一
            print('代理 %s 當(dāng)前分?jǐn)?shù) %d ==> 減1 ==> %d' % (proxy, score, score - 1))
            return self.db.zincrby(REDIS_KEY, proxy, -1)
        else:
            # 否則移除代理
            print('代理 %s 當(dāng)前分?jǐn)?shù) %d ==> 移除' % (proxy, score))
            return self.db.zrem(REDIS_KEY, proxy)

    def exists(self, proxy):
        '''
        代理是否存在
        :param proxy: 代理
        :return: 是否存在
        '''
        return self.db.zscore(REDIS_KEY, proxy) is not None

    def set_max(self, proxy):
        '''
        將代理設(shè)置為最大分?jǐn)?shù)
        :param proxy: 代理
        :return: 設(shè)置結(jié)果
        '''
        print('代理 %s 可用 ==> 設(shè)置為 %d' % (proxy, MAX_SCORE))
        return self.db.zadd(REDIS_KEY, MAX_SCORE, proxy)

    def count(self):
        '''
        獲取代理數(shù)量
        :return: 數(shù)量
        '''
        return self.db.zcard(REDIS_KEY)

    def all(self):
        '''
        獲取全部代理
        :return: 全部代理
        '''
        return self.db.zrangebyscore(REDIS_KEY, MIN_SCORE, MAX_SCORE)


if __name__ == '__main__':
    # 進(jìn)行一些測試
    redis_cli = RedisCli()
    proxy = '118.25.220.214:3128'
    redis_cli.add(proxy)
    redis_cli.set_max(proxy)
    redis_cli.decrease(proxy)
    print(redis_cli.exists(proxy))
    print(redis_cli.count())
    print(redis_cli.all())
    redis_cli.add('140.227.60.114:3128')
    redis_cli.add('213.128.7.72:53281')
    redis_cli.add('37.187.149.129:1080')
    redis_cli.set_max('140.227.60.114:3128')
    print(redis_cli.random())


這里我們使用了Redis 有序集合(sorted set)

  • Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復(fù)的成員绎速。
  • 不同的是每個元素都會關(guān)聯(lián)一個double類型的分?jǐn)?shù)纹冤。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序购公。
  • 有序集合的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。
  • 集合是通過哈希表實(shí)現(xiàn)的知残,所以添加比庄,刪除,查找的復(fù)雜度都是O(1)佳窑。 集合中最大的成員數(shù)為 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。

本節(jié)代碼戳我

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末净神,一起剝皮案震驚了整個濱河市溉委,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坡慌,老刑警劉巖藻三,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異梨树,居然都是意外死亡岖寞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進(jìn)店門指巡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人藻雪,你說我怎么就攤上這事≈讣澹” “怎么了便斥?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長枢纠。 經(jīng)常有香客問我,道長镰绎,這世上最難降的妖魔是什么木西? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮户魏,結(jié)果婚禮上叼丑,老公的妹妹穿的比我還像新娘扛门。我一直安慰自己,他們只是感情好论寨,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布葬凳。 她就那樣靜靜地躺著,像睡著了一般火焰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天绒怨,我揣著相機(jī)與錄音南蹂,去河邊找鬼。 笑死六剥,一個胖子當(dāng)著我的面吹牛樊诺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播词爬,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼顿膨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了恋沃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤恕洲,失蹤者是張志新(化名)和其女友劉穎梅割,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體户辞,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年刃榨,在試婚紗的時候發(fā)現(xiàn)自己被綠了枢希。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朱沃。...
    茶點(diǎn)故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖呕屎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情秀睛,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布椭迎,位于F島的核電站田盈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏允瞧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一痹升、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疼蛾,春花似錦艺配、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酝掩。三九已至眷柔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驯嘱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工照棋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琴许。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓晾浴,卻偏偏與公主長得像牍白,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茂腥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容