摘要:下面清單展示了地址所屬地查找程序的具體實現方法將地址轉換為分值以便執行命令查找唯一城市方法用來根據指定的分隔符將字符串進行分割。
上一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第2節:計數器和統計數據
下一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第4節:服務的發現與配置
通過將統計數據和日志存儲到Redis里面,我們可以收集訪客在系統中的行為信息。但是直到目前為止,我們都忽略了訪客行為中非常重要的一部分,那就是:這些訪客是從哪里來的?為了回答這個問題,在這一節中,我們將構建一系列用于分析和載入IP所屬地數據庫的函數,并編寫一個可以根據訪客的IP地址來查找訪客所在城市、行政區、國家的函數。我們先來看看下面這個例子。
隨著Fake Game公司的游戲越來越受追捧,來自世界各地的玩家也越來越多。盡管像Google Analytics這樣的工具可以讓Fake Game公司知道玩家主要來自哪些國家或地區,但是為了更深入的了解玩家,Fake Game公司還希望自己能夠知道玩家們所在的城市,而我們要做的就是將一個IP所屬城市數據庫載入Redis里面,然后通過搜索整個數據庫來發現玩家所在的位置。
我們之所以使用Redis而不是傳統的關系數據庫來實現IP所屬地查找功能,是因為Redis實現的IP所屬地查找程序在運行速度上更具有優勢。另一方面,因為對用戶進行定位所需的信息量非常龐大,在應用程序啟動時載入這些信息將影響應用程序的啟動速度,所以我們也沒有使用本地查找表來實現IP所屬地查找功能。實現IP所屬地查找功能首先要做的就是將一些數據表載入Redis里面,接下來的小節將對這個步驟進行介紹。
載入城市表格為了開發IP所屬地查找程序,我們將使用一個IP所屬城市數據庫作為測試數據。這個數據庫包含兩個非常重要的文件:
一個是GeoLiteCity-Blocks.csv,它記錄了多個IP地址段以及這些地址段所屬城市的ID
另一個是GeoLiteCity-Location.csv它記錄了城市ID與城市名、地區名、州縣名以及我們不會用到的其他信息之間的映射。
實現IP所屬地查找程序會用到兩個查找表:
第一個查找表需要根據輸入的IP地址來查找IP所屬城市的ID
第二個查找表則需要根據輸入的城市ID來查找ID對應城市的實際信息(這個城市信息中還會包括城市所在地區的其他信息)
根據IP地址來查找城市ID的查找表由有序集合實現,這個有序集合的成員為具體的城市ID,而分值則是一個根據IP地址計算出來的整數值。為了創建IP地址與城市ID之間的映射,程序需要將點分十進制格式的IP地址轉換為一個整數分值,下面的ip_to_score()函數定義了整個轉化過程:IP地址中的每8個二進制會被看做是無符號整數中的1字節,其中IP地址最開頭的8個二進制位最高位。
def ip_ti_score(ip_address): score=0 for v in ip_address.split("."): score=score*256+int(v,10) return score if __name__ == "__main__": y=ip_ti_score("117.61.12.128") print(y) x=117 x=x*256+61 x=x*256+12 x=x*256+128 print(x)
運行結果:
1966935168 1966935168
在將IP地址轉換為整數分值之后,程序就可以創建IP地址與城市ID之間的映射了。因為多個IP地址范圍可能會被映射到同一個城市ID,所以程序會在普通的城市ID后面,加上一個_字符以及有序集合目前已知的城市ID的數量,以此來構建一個獨一無二的唯一城市ID。下面代碼展示了程序時如何創建IP地址與城市ID之前的映射的。
import csv #這個函數在執行時需要輸入GeoLiteCity-Blocks.csv文件所在的路徑 def import_ips_to_redis(conn,filename): csv_file=csv.reader(open(filename,"rb")) #enumerate() 函數用于將一個可遍歷的數據對象(如列表、元組或字符串)組合為一個索引序列, # 同時列出數據和數據下標,一般用在 for 循環當中。 for count,row in enumerate(csv_file): start_ip=row[0] if row else "" #按照需要將IP地址轉換為分值 if "i" in start_ip.lower(): continue if "." in start_ip: start_ip=ip_to_score(start_ip) elif start_ip.isdigit(): start_ip=int(start_ip,10) else: #略過文件的第一行以及格式不正確的條目 continue #構建唯一的城市ID city_id=row[2]+"_"+str(count) #將城市ID及其對應的IP地址分值添加到有序集合里面。 conn_zadd("ip2cityid:",city_id,start_ip)
在調用import_ips_to_redis()函數并將所有IP地址都載入Redis之后,我們會像下面代碼展示的那樣,創建一個城市ID映射至城市信息的散列。因為所有城市信息的格式都是固定的,并且不會隨著時間而發生變化,所有我們會將這些信息編碼為JSON列表然后再進行存儲。
def import_cities_to_redis(conn,filename): for row in csv.reader(open(filename,"rb")): if len(row)<4 or not row[0].isdigit(): continue row=[i.decode("latin-1") for i in row] city_id=row[0] country=row[1] region=row[2] city=row[3] conn.hset("cityid2city:",city_id,json.dumps([city,region,country]))
在將所需的信息全部存儲到Redis里面之后,接下來要考慮的就是如何實現IP地址查找功能了。
查找IP所屬城市為了實現IP地址查找功能,我們在上一個小節已經將代表城市ID所屬IP地址段起始端的整數分值添加到了有序集合里面。要根據給定IP地址來查找所屬城市,程序首先會使用ip_to_score()函數將給定的IP地址轉換為分值,然后在所有分值小于或等于給定IP地址里面,找出分值最大的那個IP地址所對應的城市ID。這個查找城市ID的操作可以通過調用zrevrangebyscore命令并將選項start和num的參數分別設為0和1來完成。在找到城市ID之后,程序就可以在存儲著城市ID與城市信息映射的散列里面獲取ID對應城市的信息了。
下面清單展示了IP地址所屬地查找程序的具體實現方法:;
def find_city_by_ip(conn,ip_address): if isinstance(ip_address,str): #將IP地址轉換為分值以便執行zrevrangebyscore命令 ip_address=ip_to_score(ip_address) #查找唯一城市ID city_id=conn.zrevrangebyscore("ip2cityed:",ip_address,0,start=0,num=1) if not city_id: return None #partition() 方法用來根據指定的分隔符將字符串進行分割。 # 如果字符串包含指定的分隔符,則返回一個3元的元組, # 第一個為分隔符左邊的子串,第二個為分隔符本身,第三個為分隔符右邊的子串。 #將唯一城市ID轉換為普通城市ID city_id=city_id[0].partition("_")[0] #從散列里面取出城市信息 return json.loads(conn.hget("cityid2city:",city_id))
通過上面函數,我們現在可以基于IP地址來查找相應的城市信息并對用戶的來源地進行分析了。
本節介紹的【將數據轉換為整數并搭配有序集合進行操作】的做法非常有用,它可以極大簡化對特定元素或特定范圍的查找工作。
上一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第2節:計數器和統計數據
下一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第4節:服務的發現與配置
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/42725.html
摘要:在通常情況下,即使只更新配置中的一個標志,也會導致更新后的配置文件被強制推送至所有服務器,收到更新的服務器可能需要重新載入配置甚至可能還要重啟應用程序服務器。將被包裹函數的一些有用的元數據復制給配置處理器。 上一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第3節:查找IP所屬城市以及國家 隨著我們越來越多地使用Redis以及其他服務,如何存儲各項服務的...
摘要:清理程序通過對記錄已知計數器的有序集合執行命令來一個接一個的遍歷所有已知的計數器。 上一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第1節:使用Redis來記錄日志下一篇文章:Python--Redis實戰:第五章:使用Redis構建支持程序:第3節:查找IP所屬城市以及國家 正如第三章所述,通過記錄各個頁面的被訪問次數,我們可以根據基本的訪問計數信息...
閱讀 980·2023-04-25 23:55
閱讀 2702·2023-04-25 14:13
閱讀 3295·2019-08-26 13:47
閱讀 2968·2019-08-23 18:16
閱讀 625·2019-08-23 17:20
閱讀 3227·2019-08-23 16:55
閱讀 3144·2019-08-22 15:39
閱讀 3192·2019-08-20 18:10