這篇文章給大家分享的是有關(guān)Python搭建代理IP池實現(xiàn)存儲IP的示例的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
創(chuàng)新互聯(lián)科技有限公司專業(yè)互聯(lián)網(wǎng)基礎(chǔ)服務(wù)商,為您提供德陽服務(wù)器托管,高防主機,成都IDC機房托管,成都主機托管等互聯(lián)網(wǎng)服務(wù)。存儲的方式有很多,直接一點的可以放在一個文本文件中,但操作起來不太靈活,而我選擇的是 MySQL 數(shù)據(jù)庫,因為數(shù)據(jù)庫便于管理而且功能強大,當(dāng)然你還可以選擇其他數(shù)據(jù)庫,比如 MongoDB、Redis 等。
使用的庫:pymysql
定義規(guī)則
數(shù)據(jù)庫存儲的主要對象是各個 IP,首先需要保證不重復(fù),另外還需要標(biāo) IP 的可用情況,而且需要動態(tài)實時處理每個 IP,因此還需要定義一個分?jǐn)?shù)字段,分?jǐn)?shù)是可以重復(fù)的,最好是整數(shù)類型,每個 IP 都有一個分?jǐn)?shù),表現(xiàn)其可用性
對于代理池來說,分?jǐn)?shù)可以作為我們判斷一個代理可用不可用的標(biāo)志,我們將設(shè)置一個最高分(滿分,值由自己設(shè)置),代表可用,0 設(shè)為最低分,代表不可用。從代理池中獲取代理的時候會先從滿分 IP 中隨機獲取一個,注意這里是隨機,這樣可以保證每個可用 IP 都會被調(diào)用到,如果沒有滿分的就從所有 IP 從隨機選一個
分?jǐn)?shù)規(guī)則如下:
滿分為可用,檢測器會定時循環(huán)檢測每個 IP 的可用情況,一旦檢測到有可用的 IP 就立即置為滿分,檢測到不可用就將分?jǐn)?shù)減 1,減至 0 后移除。
新獲取的代理添加時將分?jǐn)?shù)置為 10,當(dāng)測試可行立即置 100,不可行分?jǐn)?shù)減 1,減至 0 后移除
添加設(shè)置
先在一個文件中定義一些配置信息,如數(shù)據(jù)庫的設(shè)置、一些不變量如滿分的數(shù)值等
setting.py
# 數(shù)據(jù)庫地址 HOST = '127.0.0.1' # MySql端口 MYSQL_PORT = 3306 # MySQl用戶名、密碼 MYSQL_USERNAME = '***' MYSQL_PASSWORD = '***' # 數(shù)據(jù)庫名 SQL_NAME = 'test' # 代理等級 MAX_SCORE = 30 MIN_SCORE = 0 INITIAL_SCORE = 10 # 代理池數(shù)量界限 POOL_UPPER_THRESHOLD = 1000
MAX_SCORE、MIN_SCORE、INITIAL_SCORE 分別代表大分?jǐn)?shù)、最小分?jǐn)?shù)、初始分?jǐn)?shù)
定義方法
定義一個類來操作數(shù)據(jù)庫的有序集合,內(nèi)含一些方法來實現(xiàn)分?jǐn)?shù)的設(shè)置、代理的獲取等
db.py
import pymysql from error import PoolEmptyError from setting import * from random import choice import re class MySqlClient(object): # 初始化 def __init__(self, host=HOST, port=MYSQL_PORT, username=MYSQL_USERNAME, password=MYSQL_PASSWORD, sqlname=SQL_NAME): self.db = pymysql.connect(host=host, user=username, password=password, port=port, db=sqlname) self.cursor = self.db.cursor() # 添加代理IP def add(self, ip, score=INITIAL_SCORE): sql_add = "INSERT INTO PROXY (IP,SCORE) VALUES ('%s', %s)" % (ip, score) if not re.match('\d+\.\d+\.\d+\.\d+\:\d+', ip): print('代理不符合規(guī)范', ip, '丟棄') return if not self.exists(ip): self.cursor.execute(sql_add) self.db.commit() # 減少代理分?jǐn)?shù) def decrease(self, ip): sql_get = "SELECT * FROM PROXY WHERE IP='%s'" % (ip) self.cursor.execute(sql_get) score = self.cursor.fetchone()[1] print(score) if score and score > MIN_SCORE: print('代理', ip, '當(dāng)前分?jǐn)?shù)', score, '減1') sql_change = "UPDATE PROXY SET SCORE = %s WHERE IP = '%s'" % (score-1, ip) else: print('代理', ip, '當(dāng)前分?jǐn)?shù)', score, '移除') sql_change = "DELETE FROM PROXY WHERE IP = %s" % (ip) self.cursor.execute(sql_change) self.db.commit() # 分?jǐn)?shù)大化 def max(self, ip): print('代理', ip, '可用,設(shè)置為', MAX_SCORE) sql_max = "UPDATE PROXY SET SCORE = %s WHERE IP = '%s'" % (MAX_SCORE, ip) self.cursor.execute(sql_max) self.db.commit() # 隨機獲取有效代理 def random(self): # 先從滿分中隨機選一個 sql_max = "SELECT * FROM PROXY WHERE SCORE=%s" % (MAX_SCORE) if self.cursor.execute(sql_max): results = self.cursor.fetchall() return choice(results)[0] # 沒有滿分則隨機選一個 else: sql_all = "SELECT * FROM PROXY WHERE SCORE BETWEEN %s AND %s" % (MIN_SCORE, MAX_SCORE) if self.cursor.execute(sql_all): results = self.cursor.fetchall() return choice(results)[0] else: raise PoolEmptyError # 判斷是否存在 def exists(self, ip): sql_exists = "SELECT 1 FROM PROXY WHERE IP='%s' limit 1" % ip return self.cursor.execute(sql_exists) # 獲取數(shù)量 def count(self): sql_count = "SELECT * FROM PROXY" return self.cursor.execute(sql_count) # 獲取全部 def all(self): self.count() return self.cursor.fetchall() # 批量獲取 def batch(self, start, stop): sql_batch = "SELECT * FROM PROXY LIMIT %s, %s" % (start, stop - start) self.cursor.execute(sql_batch) return self.cursor.fetchall()
方法作用:
init():初始化的方法,參數(shù)是 MySQL 的連接信息,默認(rèn)的連接信息已經(jīng)定義為常量,在 init() 方法中初始化建立 MySQL 連接。這樣當(dāng) MySqlClient 類初始化的時候就建立了 MySQL 的連接
add():向數(shù)據(jù)庫添加代理并設(shè)置分?jǐn)?shù),默認(rèn)的分?jǐn)?shù)是 INITIAL_SCORE 也就是 10,返回結(jié)果是添加的結(jié)果
decrease():在 檢測無效的時候設(shè)置分?jǐn)?shù)減 1 的方法,傳入代理,然后將此代理的分?jǐn)?shù)減 1,如果達到最低值就刪除
max():將代理的分?jǐn)?shù)設(shè)置為 MAX_SCORE,也就是當(dāng) IP 有效時的設(shè)置
random():隨機獲取 IP 的方法,首先獲取滿分的 IP,然后隨機選擇一個返回,如果不存在滿分的 IP,則隨機選擇一個返回,否則拋出異常
exists():判斷 IP 是否存在于數(shù)據(jù)庫中
count():返回當(dāng)前 IP個數(shù)
all():返回所有的 IP,供檢測使用
batch():返回數(shù)據(jù)庫中從第 start 行開始(從0開始數(shù))的共 stop-start 行數(shù)據(jù)
抓取保存
當(dāng)數(shù)據(jù)庫設(shè)置好了之后,就可以直接把抓取的 IP 直接放在數(shù)據(jù)庫中了
直接把前面用到的抓取代碼更改一下就行了
getter.py
from crawler import Crawler from db import MySqlClient from setting import * import sys class Getter(): def __init__(self): self.mysql = MySqlClient() self.crawler = Crawler() # 判斷數(shù)量是否足夠 def is_over_threshold(self): if self.mysql.count() >= POOL_UPPER_THRESHOLD: return True else: return False def run(self): print('獲取器開始執(zhí)行') if not self.is_over_threshold(): for callback_label in range(self.crawler.__CrawlFuncCount__): callback = self.crawler.__CrawlFunc__[callback_label] # 獲取代理 all_ip = self.crawler.get_proxies(callback) sys.stdout.flush() for ip in all_ip: self.mysql.add(ip) if __name__ == '__main__': get = Getter() get.run()
結(jié)果:
感謝各位的閱讀!關(guān)于“Python搭建代理IP池實現(xiàn)存儲IP的示例”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站欄目:Python搭建代理IP池實現(xiàn)存儲IP的示例-創(chuàng)新互聯(lián)
地址分享:http://aaarwkj.com/article38/dpgosp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、網(wǎng)站導(dǎo)航、微信小程序、靜態(tài)網(wǎng)站、用戶體驗、品牌網(wǎng)站設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容