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人人网登录应用实例
Sep 26 Python
python验证码识别的实例详解
Sep 09 Python
Python二叉树定义与遍历方法实例分析
May 25 Python
Python 删除连续出现的指定字符的实例
Jun 29 Python
Python元组知识点总结
Feb 18 Python
python openpyxl使用方法详解
Jul 18 Python
使用python telnetlib批量备份交换机配置的方法
Jul 25 Python
Python使用贪婪算法解决问题
Oct 22 Python
python开发入门——列表生成式
Sep 03 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
Sep 30 Python
UI自动化定位常用实现方法代码示例
Oct 27 Python
python time.strptime格式化实例详解
Feb 03 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
Zend引擎的发展 [15]
2006/10/09 PHP
增加反向链接的101个方法 站长推荐
2007/01/31 PHP
实现了一个PHP5的getter/setter基类的代码
2007/02/25 PHP
创建无限极分类树型结构的简单方法
2017/06/20 PHP
php递归函数怎么用才有效
2018/02/24 PHP
PHP里的$_GET数组介绍
2019/03/22 PHP
关于恒等于(===)和非恒等于(!==)
2007/08/20 Javascript
提交表单时执行func方法实现代码
2013/03/17 Javascript
jquery实现弹出层完美居中效果
2014/03/03 Javascript
js限制checkbox选中个数以限制六个为例
2014/07/15 Javascript
jquery和js实现对div的隐藏和显示方法
2014/09/26 Javascript
js实现点击链接后窗口缩小并居中的方法
2015/03/02 Javascript
分享十五款 jQuery 社交网络分享插件
2015/05/16 Javascript
jQuery简单验证上传文件大小及类型的方法
2016/06/02 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
2016/11/16 Javascript
微信小程序实现图片预加载组件
2017/01/18 Javascript
Vue实现动态创建和删除数据的方法
2018/03/17 Javascript
JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解
2019/08/16 Javascript
jQuery实现移动端图片上传预览组件的方法分析
2020/05/01 jQuery
Python3.2中的字符串函数学习总结
2015/04/23 Python
python中字符串类型json操作的注意事项
2017/05/02 Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
2018/07/04 Python
使用TensorFlow实现SVM
2018/09/06 Python
python根据文章标题内容自动生成摘要的实例
2019/02/21 Python
Python 串口通信的实现
2020/09/29 Python
Tory Burch美国官方网站:美国时尚生活品牌
2016/08/01 全球购物
世界上最大的字体市场:MyFonts
2020/01/10 全球购物
光电信息专业应届生求职信
2013/10/07 职场文书
社区学习十八大感想
2014/01/22 职场文书
酒店员工职业生涯规划
2014/02/25 职场文书
专科应届毕业生求职信
2014/06/04 职场文书
幼儿园清明节活动总结
2014/07/04 职场文书
2015年春节标语口号
2014/12/09 职场文书
个人房屋租赁合同(标准范本)
2019/09/16 职场文书
mysql中varchar类型的日期进行比较、排序等操作的实现
2021/11/17 MySQL
vue2的 router在使用过程中遇到的一些问题
2022/04/13 Vue.js