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 08 Python
深入理解Python装饰器
Jul 27 Python
Python自动化测试ConfigParser模块读写配置文件
Aug 15 Python
如何在Python中实现goto语句的方法
May 18 Python
python3 线性回归验证方法
Jul 09 Python
django创建超级用户过程解析
Sep 18 Python
Python jieba库用法及实例解析
Nov 04 Python
Python random库使用方法及异常处理方案
Mar 02 Python
使用Python将图片转正方形的两种方法实例代码详解
Apr 29 Python
属性与 @property 方法让你的python更高效
Sep 21 Python
Django Form常用功能及代码示例
Oct 13 Python
python解析json数据
Apr 29 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
PHP array_multisort()函数的使用札记
2011/07/03 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
PHP实现的增强性mhash函数
2015/05/27 PHP
PHP编译configure时常见错误的总结
2017/08/17 PHP
PHP工厂模式简单实现方法示例
2018/05/23 PHP
图片自动更新(说明)
2006/10/02 Javascript
浅析JavaScript原型继承的陷阱
2013/12/03 Javascript
表格奇偶行设置不同颜色的核心JS代码
2013/12/24 Javascript
Egret引擎开发指南之编译项目
2014/09/03 Javascript
JavaScript中的数值范围介绍
2014/12/29 Javascript
javascript无刷新评论实现方法
2015/05/13 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
每天一篇javascript学习小结(面向对象编程)
2015/11/20 Javascript
微信小程序 input表单与redio及下拉列表的使用实例
2017/09/20 Javascript
JavaScript数组排序reverse()和sort()方法详解
2017/12/24 Javascript
ES6使用export和import实现模块化的方法
2018/09/10 Javascript
详解在不使用ssr的情况下解决Vue单页面SEO问题
2018/11/08 Javascript
Vue.js实现可排序的表格组件功能示例
2019/02/19 Javascript
JS开发常用工具函数(小结)
2019/07/04 Javascript
python实现发送邮件功能代码
2017/12/14 Python
Python中print和return的作用及区别解析
2019/05/05 Python
Python 根据日志级别打印不同颜色的日志的方法示例
2019/08/08 Python
Python输出指定字符串的方法
2020/02/06 Python
Python enumerate内置库用法解析
2020/02/24 Python
Python爬虫之Selenium多窗口切换的实现
2020/12/04 Python
h5移动端调用支付宝、微信支付的实现
2020/06/08 HTML / CSS
英国第一独立滑雪板商店:The Snowboard Asylum
2020/01/16 全球购物
大二学生学习个人自我评价
2014/01/19 职场文书
妇联领导班子剖析材料
2014/08/21 职场文书
2014年财务人员工作总结
2014/11/11 职场文书
不服劳动仲裁起诉书
2015/05/20 职场文书
企业宣传语大全
2015/07/13 职场文书
办公室卫生管理制度
2015/08/04 职场文书
小学数学教师研修感悟
2015/11/18 职场文书
Oracle 区块链表创建过程详解
2021/05/15 Oracle
详解Vue项目的打包方式(生成dist文件)
2022/01/18 Vue.js