Python实现短网址ShortUrl的Hash运算实例讲解


Posted in Python onAugust 10, 2015

本文实例讲述了Python实现短网址ShortUrl的Hash运算方法。分享给大家供大家参考。具体如下:

shorturl实现常见的做法都是将原始Url存储到数据库,由数据库返回一个对应ID。

以下要实现的是不用数据库支持就对原始URL进行shorturl hash。说到这里我们很容易想到MD5,固定长度,冲突概率小,但是32个字符,太长?我们以MD5为基础,将其字符缩短,同时要保证一定数量范围内hash不会冲突。

我们分成两个步骤来实现。

第一步算法:

① 将长网址用md5算法生成32位签名串,分为4段,,每段8个字符;
② 对这4段循环处理,取每段的8个字符, 将他看成16进制字符串与0x3fffffff(30位1)的位与操作,超过30位的忽略处理;
③ 将每段得到的这30位又分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串;
④ 这样一个md5字符串可以获得4个6位串,取里面的任意一个就可作为这个长url的短url地址。
(出现重复的几率大约是n/(32^6) 也就是n/1,073,741,824,其中n是数据库中记录的条数)

我们就得到了4个6位串,可是选哪个作为最终的hash结果呢,随机选肯定是不行的,同样的url两次hash就会得出不同的结果。接下来根据原始url的特征进行选择,并且将hash冲突的可能性控制在同一个domain内:

第二步算法:

①从原始url中提取域名,提取数字(最多后6位);
②将所得的数字与4取模,根据所得的余数决定从第一步算法中得到的4个shorturl中选取哪一个;
③从域名中提取特征串:一级域名中的第一个字符和后面二个辅音(如果辅音不足2个取任意前两个);
④域名特征串和选定的shorturl拼接成9位字符为最终的shorturl;
(后两个步骤是将冲突控制在一个domain内)

ShortUrl.py

#encoding:utf-8
__author__ = 'James Lau'
import hashlib
import re
def __original_shorturl(url):
  '''
  算法:
  ① 将长网址用md5算法生成32位签名串,分为4段,,每段8个字符;
  ② 对这4段循环处理,取每段的8个字符, 将他看成16进制字符串与0x3fffffff(30位1)的位与操作,超过30位的忽略处理;
  ③ 将每段得到的这30位又分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串;
  ④ 这样一个md5字符串可以获得4个6位串,取里面的任意一个就可作为这个长url的短url地址。
  (出现重复的几率大约是n/(32^6) 也就是n/1,073,741,824,其中n是数据库中记录的条数)
  '''
  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):
  '''
  算法:
  ①从原始url中提取域名,提取数字(最多后6位);
  ②将所得的数字与4取模,根据所得的余数决定从第一步算法中得到的4个shorturl中选取哪一个;
  ③从域名中提取特征串:一级域名中的第一个字符和后面二个辅音(如果辅音不足2个取任意前两个);
  ④域名特征串和选定的shorturl拼接成9位字符为最终的shorturl;
  (后两个步骤是将冲突控制在一个domain内)
  '''
  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

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
Python中__call__用法实例
Aug 29 Python
在Python中使用SimpleParse模块进行解析的教程
Apr 11 Python
Python实现端口检测的方法
Jul 24 Python
Python单向链表和双向链表原理与用法实例详解
Aug 31 Python
解决pandas.DataFrame.fillna 填充Nan失败的问题
Nov 06 Python
Python 随机生成测试数据的模块:faker基本使用方法详解
Apr 09 Python
keras 两种训练模型方式详解fit和fit_generator(节省内存)
Jul 03 Python
Python爬虫回测股票的实例讲解
Jan 22 Python
Python实现微信表情包炸群功能
Jan 28 Python
python人工智能human learn绘图可创建机器学习模型
Nov 23 Python
方法汇总:Python 安装第三方库常用
Apr 26 Python
Pygame游戏开发之太空射击实战敌人精灵篇
Aug 05 Python
python实现web方式logview的方法
Aug 10 #Python
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
Aug 10 #Python
python用10行代码实现对黄色图片的检测功能
Aug 10 #Python
详解Python中dict与set的使用
Aug 10 #Python
分析并输出Python代码依赖的库的实现代码
Aug 09 #Python
python根据京东商品url获取产品价格
Aug 09 #Python
python制作一个桌面便签软件
Aug 09 #Python
You might like
Smarty的配置与高级缓存技术分享
2012/06/05 PHP
php实现的返回数据格式化类实例
2014/09/22 PHP
PHP实现阿里大鱼短信验证的实例代码
2017/07/10 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
浅析Bootstrap验证控件的使用
2016/06/23 Javascript
微信支付 JS API支付接口详解
2016/07/11 Javascript
AngularJS使用自定义指令替代ng-repeat的方法
2016/09/17 Javascript
js实现简单的网页换肤效果
2017/01/18 Javascript
JavaScript中for循环的几种写法与效率总结
2017/02/03 Javascript
javascript中神奇的 Date对象小结
2017/10/12 Javascript
vue中tab选项卡的实现思路
2018/11/25 Javascript
Vue.js上传图片到阿里云OSS存储的方法示例
2018/12/13 Javascript
vue router 用户登陆功能的实例代码
2019/04/24 Javascript
layui 上传文件_批量导入数据UI的方法
2019/09/23 Javascript
vue实现在线翻译功能
2019/09/27 Javascript
Vue 实现显示/隐藏层的思路(加全局点击事件)
2019/12/31 Javascript
Vue使用CDN引用项目组件,减少项目体积的步骤
2020/10/30 Javascript
详解如何在vue+element-ui的项目中封装dialog组件
2020/12/11 Vue.js
[01:51]2014DOTA2国际邀请赛 这个赛场没有失败者VGTi5再见
2014/07/23 DOTA
Python中使用tarfile压缩、解压tar归档文件示例
2015/04/05 Python
使用Python内置的模块与函数进行不同进制的数的转换
2016/03/12 Python
Python入门之三角函数sin()函数实例详解
2017/11/08 Python
利用 python 对目录下的文件进行过滤删除
2017/12/27 Python
Python使用matplotlib绘制正弦和余弦曲线的方法示例
2018/01/06 Python
Python之列表实现栈的工作功能
2019/01/28 Python
python中import与from方法总结(推荐)
2019/03/21 Python
Gap中国官网:美式休闲风服饰
2017/02/05 全球购物
阿里云:Aliyun.com
2017/02/15 全球购物
土建资料员岗位职责
2014/01/04 职场文书
职业生涯规划书怎么写?
2014/09/14 职场文书
大学生党员个人对照检查材料范文
2014/09/25 职场文书
学校领导四风问题整改措施思想汇报
2014/10/09 职场文书
企业务虚会发言材料
2014/10/20 职场文书
社区党支部承诺书
2015/04/29 职场文书
太空授课观后感
2015/06/17 职场文书
浅谈Java实现分布式事务的三种方案
2021/06/11 Java/Android