国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第3節(jié):查找IP所屬城市以及國家

fengxiuping / 2878人閱讀

摘要:下面清單展示了地址所屬地查找程序的具體實現(xiàn)方法將地址轉(zhuǎn)換為分值以便執(zhí)行命令查找唯一城市方法用來根據(jù)指定的分隔符將字符串進行分割。

上一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第2節(jié):計數(shù)器和統(tǒng)計數(shù)據(jù)
下一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第4節(jié):服務(wù)的發(fā)現(xiàn)與配置

通過將統(tǒng)計數(shù)據(jù)和日志存儲到Redis里面,我們可以收集訪客在系統(tǒng)中的行為信息。但是直到目前為止,我們都忽略了訪客行為中非常重要的一部分,那就是:這些訪客是從哪里來的?為了回答這個問題,在這一節(jié)中,我們將構(gòu)建一系列用于分析和載入IP所屬地數(shù)據(jù)庫的函數(shù),并編寫一個可以根據(jù)訪客的IP地址來查找訪客所在城市、行政區(qū)、國家的函數(shù)。我們先來看看下面這個例子。

隨著Fake Game公司的游戲越來越受追捧,來自世界各地的玩家也越來越多。盡管像Google Analytics這樣的工具可以讓Fake Game公司知道玩家主要來自哪些國家或地區(qū),但是為了更深入的了解玩家,F(xiàn)ake Game公司還希望自己能夠知道玩家們所在的城市,而我們要做的就是將一個IP所屬城市數(shù)據(jù)庫載入Redis里面,然后通過搜索整個數(shù)據(jù)庫來發(fā)現(xiàn)玩家所在的位置。

我們之所以使用Redis而不是傳統(tǒng)的關(guān)系數(shù)據(jù)庫來實現(xiàn)IP所屬地查找功能,是因為Redis實現(xiàn)的IP所屬地查找程序在運行速度上更具有優(yōu)勢。另一方面,因為對用戶進行定位所需的信息量非常龐大,在應(yīng)用程序啟動時載入這些信息將影響應(yīng)用程序的啟動速度,所以我們也沒有使用本地查找表來實現(xiàn)IP所屬地查找功能。實現(xiàn)IP所屬地查找功能首先要做的就是將一些數(shù)據(jù)表載入Redis里面,接下來的小節(jié)將對這個步驟進行介紹。

載入城市表格

為了開發(fā)IP所屬地查找程序,我們將使用一個IP所屬城市數(shù)據(jù)庫作為測試數(shù)據(jù)。這個數(shù)據(jù)庫包含兩個非常重要的文件:

一個是GeoLiteCity-Blocks.csv,它記錄了多個IP地址段以及這些地址段所屬城市的ID

另一個是GeoLiteCity-Location.csv它記錄了城市ID與城市名、地區(qū)名、州縣名以及我們不會用到的其他信息之間的映射。

實現(xiàn)IP所屬地查找程序會用到兩個查找表:

第一個查找表需要根據(jù)輸入的IP地址來查找IP所屬城市的ID

第二個查找表則需要根據(jù)輸入的城市ID來查找ID對應(yīng)城市的實際信息(這個城市信息中還會包括城市所在地區(qū)的其他信息)

根據(jù)IP地址來查找城市ID的查找表由有序集合實現(xiàn),這個有序集合的成員為具體的城市ID,而分值則是一個根據(jù)IP地址計算出來的整數(shù)值。為了創(chuàng)建IP地址與城市ID之間的映射,程序需要將點分十進制格式的IP地址轉(zhuǎn)換為一個整數(shù)分值,下面的ip_to_score()函數(shù)定義了整個轉(zhuǎn)化過程:IP地址中的每8個二進制會被看做是無符號整數(shù)中的1字節(jié),其中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)

運行結(jié)果:

1966935168
1966935168

在將IP地址轉(zhuǎn)換為整數(shù)分值之后,程序就可以創(chuàng)建IP地址與城市ID之間的映射了。因為多個IP地址范圍可能會被映射到同一個城市ID,所以程序會在普通的城市ID后面,加上一個_字符以及有序集合目前已知的城市ID的數(shù)量,以此來構(gòu)建一個獨一無二的唯一城市ID。下面代碼展示了程序時如何創(chuàng)建IP地址與城市ID之前的映射的。

import csv


#這個函數(shù)在執(zhí)行時需要輸入GeoLiteCity-Blocks.csv文件所在的路徑
def import_ips_to_redis(conn,filename):
    csv_file=csv.reader(open(filename,"rb"))
    #enumerate() 函數(shù)用于將一個可遍歷的數(shù)據(jù)對象(如列表、元組或字符串)組合為一個索引序列,
    # 同時列出數(shù)據(jù)和數(shù)據(jù)下標(biāo),一般用在 for 循環(huán)當(dāng)中。
    for count,row in enumerate(csv_file):
        start_ip=row[0] if row else ""
        #按照需要將IP地址轉(zhuǎn)換為分值
        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
        #構(gòu)建唯一的城市ID
        city_id=row[2]+"_"+str(count)
        #將城市ID及其對應(yīng)的IP地址分值添加到有序集合里面。
        conn_zadd("ip2cityid:",city_id,start_ip)

在調(diào)用import_ips_to_redis()函數(shù)并將所有IP地址都載入Redis之后,我們會像下面代碼展示的那樣,創(chuàng)建一個城市ID映射至城市信息的散列。因為所有城市信息的格式都是固定的,并且不會隨著時間而發(fā)生變化,所有我們會將這些信息編碼為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里面之后,接下來要考慮的就是如何實現(xiàn)IP地址查找功能了。

查找IP所屬城市

為了實現(xiàn)IP地址查找功能,我們在上一個小節(jié)已經(jīng)將代表城市ID所屬IP地址段起始端的整數(shù)分值添加到了有序集合里面。要根據(jù)給定IP地址來查找所屬城市,程序首先會使用ip_to_score()函數(shù)將給定的IP地址轉(zhuǎn)換為分值,然后在所有分值小于或等于給定IP地址里面,找出分值最大的那個IP地址所對應(yīng)的城市ID。這個查找城市ID的操作可以通過調(diào)用zrevrangebyscore命令并將選項start和num的參數(shù)分別設(shè)為0和1來完成。在找到城市ID之后,程序就可以在存儲著城市ID與城市信息映射的散列里面獲取ID對應(yīng)城市的信息了。

下面清單展示了IP地址所屬地查找程序的具體實現(xiàn)方法:;

def find_city_by_ip(conn,ip_address):
    if isinstance(ip_address,str):
        #將IP地址轉(zhuǎn)換為分值以便執(zhí)行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() 方法用來根據(jù)指定的分隔符將字符串進行分割。
    # 如果字符串包含指定的分隔符,則返回一個3元的元組,
    # 第一個為分隔符左邊的子串,第二個為分隔符本身,第三個為分隔符右邊的子串。
    #將唯一城市ID轉(zhuǎn)換為普通城市ID
    city_id=city_id[0].partition("_")[0]
    #從散列里面取出城市信息
    return json.loads(conn.hget("cityid2city:",city_id))

通過上面函數(shù),我們現(xiàn)在可以基于IP地址來查找相應(yīng)的城市信息并對用戶的來源地進行分析了。

本節(jié)介紹的【將數(shù)據(jù)轉(zhuǎn)換為整數(shù)并搭配有序集合進行操作】的做法非常有用,它可以極大簡化對特定元素或特定范圍的查找工作。

上一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第2節(jié):計數(shù)器和統(tǒng)計數(shù)據(jù)
下一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第4節(jié):服務(wù)的發(fā)現(xiàn)與配置

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/42725.html

相關(guān)文章

  • Python--Redis實戰(zhàn)五章使用Redis構(gòu)建支持程序4節(jié):服務(wù)的發(fā)現(xiàn)與配置

    摘要:在通常情況下,即使只更新配置中的一個標(biāo)志,也會導(dǎo)致更新后的配置文件被強制推送至所有服務(wù)器,收到更新的服務(wù)器可能需要重新載入配置甚至可能還要重啟應(yīng)用程序服務(wù)器。將被包裹函數(shù)的一些有用的元數(shù)據(jù)復(fù)制給配置處理器。 上一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第3節(jié):查找IP所屬城市以及國家 隨著我們越來越多地使用Redis以及其他服務(wù),如何存儲各項服務(wù)的...

    jackzou 評論0 收藏0
  • Python--Redis實戰(zhàn)五章使用Redis構(gòu)建支持程序2節(jié):計數(shù)器和統(tǒng)計數(shù)據(jù)

    摘要:清理程序通過對記錄已知計數(shù)器的有序集合執(zhí)行命令來一個接一個的遍歷所有已知的計數(shù)器。 上一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第1節(jié):使用Redis來記錄日志下一篇文章:Python--Redis實戰(zhàn):第五章:使用Redis構(gòu)建支持程序:第3節(jié):查找IP所屬城市以及國家 正如第三章所述,通過記錄各個頁面的被訪問次數(shù),我們可以根據(jù)基本的訪問計數(shù)信息...

    sourcenode 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<