Python實(shí)現(xiàn)短網(wǎng)址ShortUrl的Hash運(yùn)算實(shí)例講解
本文實(shí)例講述了Python實(shí)現(xiàn)短網(wǎng)址ShortUrl的Hash運(yùn)算方法。分享給大家供大家參考。具體如下:
shorturl實(shí)現(xiàn)常見(jiàn)的做法都是將原始Url存儲(chǔ)到數(shù)據(jù)庫(kù),由數(shù)據(jù)庫(kù)返回一個(gè)對(duì)應(yīng)ID。
以下要實(shí)現(xiàn)的是不用數(shù)據(jù)庫(kù)支持就對(duì)原始URL進(jìn)行shorturl hash。說(shuō)到這里我們很容易想到MD5,固定長(zhǎng)度,沖突概率小,但是32個(gè)字符,太長(zhǎng)?我們以MD5為基礎(chǔ),將其字符縮短,同時(shí)要保證一定數(shù)量范圍內(nèi)hash不會(huì)沖突。
我們分成兩個(gè)步驟來(lái)實(shí)現(xiàn)。
第一步算法:
① 將長(zhǎng)網(wǎng)址用md5算法生成32位簽名串,分為4段,,每段8個(gè)字符;
② 對(duì)這4段循環(huán)處理,取每段的8個(gè)字符, 將他看成16進(jìn)制字符串與0x3fffffff(30位1)的位與操作,超過(guò)30位的忽略處理;
③ 將每段得到的這30位又分成6段,每5位的數(shù)字作為字母表的索引取得特定字符,依次進(jìn)行獲得6位字符串;
④ 這樣一個(gè)md5字符串可以獲得4個(gè)6位串,取里面的任意一個(gè)就可作為這個(gè)長(zhǎng)url的短url地址。
(出現(xiàn)重復(fù)的幾率大約是n/(32^6) 也就是n/1,073,741,824,其中n是數(shù)據(jù)庫(kù)中記錄的條數(shù))
我們就得到了4個(gè)6位串,可是選哪個(gè)作為最終的hash結(jié)果呢,隨機(jī)選肯定是不行的,同樣的url兩次hash就會(huì)得出不同的結(jié)果。接下來(lái)根據(jù)原始url的特征進(jìn)行選擇,并且將hash沖突的可能性控制在同一個(gè)domain內(nèi):
第二步算法:
①?gòu)脑紆rl中提取域名,提取數(shù)字(最多后6位);
②將所得的數(shù)字與4取模,根據(jù)所得的余數(shù)決定從第一步算法中得到的4個(gè)shorturl中選取哪一個(gè);
③從域名中提取特征串:一級(jí)域名中的第一個(gè)字符和后面二個(gè)輔音(如果輔音不足2個(gè)取任意前兩個(gè));
④域名特征串和選定的shorturl拼接成9位字符為最終的shorturl;
(后兩個(gè)步驟是將沖突控制在一個(gè)domain內(nèi))
ShortUrl.py
#encoding:utf-8 __author__ = 'James Lau' import hashlib import re def __original_shorturl(url): ''' 算法: ① 將長(zhǎng)網(wǎng)址用md5算法生成32位簽名串,分為4段,,每段8個(gè)字符; ② 對(duì)這4段循環(huán)處理,取每段的8個(gè)字符, 將他看成16進(jìn)制字符串與0x3fffffff(30位1)的位與操作,超過(guò)30位的忽略處理; ③ 將每段得到的這30位又分成6段,每5位的數(shù)字作為字母表的索引取得特定字符,依次進(jìn)行獲得6位字符串; ④ 這樣一個(gè)md5字符串可以獲得4個(gè)6位串,取里面的任意一個(gè)就可作為這個(gè)長(zhǎng)url的短url地址。 (出現(xiàn)重復(fù)的幾率大約是n/(32^6) 也就是n/1,073,741,824,其中n是數(shù)據(jù)庫(kù)中記錄的條數(shù)) ''' base32 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5' ] m = hashlib.md5() m.update(url) hexStr = m.hexdigest() hexStrLen = len(hexStr) subHexLen = hexStrLen / 8 output = [] for i in range(0,subHexLen): subHex = '0x'+hexStr[i*8:(i+1)*8] res = 0x3FFFFFFF & int(subHex,16) out = '' for j in range(6): val = 0x0000001F & res out += (base32[val]) res = res >> 5 output.append(out) return output def shorturl(url): ''' 算法: ①?gòu)脑紆rl中提取域名,提取數(shù)字(最多后6位); ②將所得的數(shù)字與4取模,根據(jù)所得的余數(shù)決定從第一步算法中得到的4個(gè)shorturl中選取哪一個(gè); ③從域名中提取特征串:一級(jí)域名中的第一個(gè)字符和后面二個(gè)輔音(如果輔音不足2個(gè)取任意前兩個(gè)); ④域名特征串和選定的shorturl拼接成9位字符為最終的shorturl; (后兩個(gè)步驟是將沖突控制在一個(gè)domain內(nèi)) ''' match_full_domain_regex = re.compile(u'^https?:\/\/(([a-zA-Z0-9_\-\.]+[a-zA-Z0-9_\-]+\.[a-zA-Z]+)|([a-zA-Z0-9_\-]+\.[a-zA-Z]+)).*$') match_full_domain = match_full_domain_regex.match(url) if match_full_domain is not None: full_domain = match_full_domain.group(1) else: return None not_numeric_regex = re.compile(u'[^\d]+') numeric_string = not_numeric_regex.sub(r'',url) if numeric_string is None or numeric_string=='': numeric_string = '0' else: numeric_string = numeric_string[-6:] domainArr = full_domain.split('.') domain = domainArr[1] if len(domainArr)==3 else domainArr[0] vowels = 'aeiou0-9' if len(domain)<=3: prefix = domain else: prefix = re.compile(u'[%s]+'%vowels).sub(r'',domain[1:]) prefix = '%s%s'%(domain[0],prefix[:2]) if len(prefix)>=2 else domain[0:3] t_shorturl = __original_shorturl(url) t_choose = int(numeric_string)%4 result = '%s%s'%(prefix,t_shorturl[t_choose]) return result
希望本文所述對(duì)大家的Python程序設(shè)計(jì)有所幫助。
- Python中使用hashlib模塊處理算法的教程
- python中hashlib模塊用法示例
- Python基于hashlib模塊的文件MD5一致性加密驗(yàn)證示例
- Python內(nèi)置模塊hashlib、hmac與uuid用法分析
- Python3 加密(hashlib和hmac)模塊的實(shí)現(xiàn)
- python中的hashlib和base64加密模塊使用實(shí)例
- 利用Python如何生成hash值示例詳解
- Python實(shí)現(xiàn)通過(guò)文件路徑獲取文件hash值的方法
- python實(shí)現(xiàn)simhash算法實(shí)例
- Python hashlib模塊用法實(shí)例分析
相關(guān)文章
Python中的lambda和apply用法及說(shuō)明
這篇文章主要介紹了Python中的lambda和apply用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12python 如何將帶小數(shù)的浮點(diǎn)型字符串轉(zhuǎn)換為整數(shù)
在python中如何實(shí)現(xiàn)將帶小數(shù)的浮點(diǎn)型字符串轉(zhuǎn)換為整數(shù)呢?今天小編就為大家介紹一下解決方案,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05Python學(xué)習(xí)工具jupyter notebook安裝及用法解析
這篇文章主要介紹了Python學(xué)習(xí)工具jupyter notebook安裝及用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10python將數(shù)據(jù)插入數(shù)據(jù)庫(kù)的代碼分享
在本篇文章里小編給大家整理的是關(guān)于python將數(shù)據(jù)插入數(shù)據(jù)庫(kù)的代碼內(nèi)容,有興趣的朋友們可以參考下。2020-08-08python numpy中setdiff1d的用法說(shuō)明
這篇文章主要介紹了python numpy中setdiff1d的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04Python?matplotlib繪圖時(shí)使用鼠標(biāo)滾輪放大/縮小圖像
Matplotlib是Python程序員可用的事實(shí)上的繪圖庫(kù),雖然它比交互式繪圖庫(kù)在圖形上更簡(jiǎn)單,但它仍然可以一個(gè)強(qiáng)大的工具,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib繪圖時(shí)使用鼠標(biāo)滾輪放大/縮小圖像的相關(guān)資料,需要的朋友可以參考下2022-05-05