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 logging 日志轮转文件不删除问题的解决方法
Aug 02 Python
windows及linux环境下永久修改pip镜像源的方法
Nov 28 Python
利用python批量修改word文件名的方法示例
Oct 17 Python
Python3数字求和的实例
Feb 19 Python
Python开启线程,在函数中开线程的实例
Feb 22 Python
详解Python中的内建函数,可迭代对象,迭代器
Apr 29 Python
python输出带颜色字体实例方法
Sep 01 Python
Python numpy.zero() 初始化矩阵实例
Nov 27 Python
Python实现代码块儿折叠
Apr 15 Python
浅谈pytorch 模型 .pt, .pth, .pkl的区别及模型保存方式
May 25 Python
解决pip install psycopg2出错问题
Jul 09 Python
python+selenium实现12306模拟登录的步骤
Jan 21 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第一季视频教程(李炎恢+php100 不断更新)
2011/05/29 PHP
php异步多线程swoole用法实例
2014/11/14 PHP
JS与框架页的操作代码
2010/01/17 Javascript
如何阻止复制剪切和粘贴事件为了表单内容的安全
2013/05/23 Javascript
全系IE支持Bootstrap的解决方法
2015/10/19 Javascript
jquery关于事件冒泡和事件委托的技巧及阻止与允许事件冒泡的三种实现方法
2015/11/27 Javascript
jquery easyui validatebox remote的使用详解
2016/11/09 Javascript
node.js 利用流实现读写同步,边读边写的方法
2017/09/11 Javascript
jQuery实现的简单前端搜索功能示例
2017/10/28 jQuery
浅谈Node.js 沙箱环境
2018/05/15 Javascript
vscode下的vue文件格式化问题
2018/11/28 Javascript
vue指令之表单控件绑定v-model v-model与v-bind结合使用
2019/04/17 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
[41:56]Spirit vs Liquid Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
两个使用Python脚本操作文件的小示例分享
2015/08/27 Python
Python数据库的连接实现方法与注意事项
2016/02/27 Python
对pandas replace函数的使用方法小结
2018/05/18 Python
详解Python连接MySQL数据库的多种方式
2019/04/16 Python
python默认参数调用方法解析
2020/02/09 Python
python实现猜数游戏
2020/03/27 Python
keras自定义损失函数并且模型加载的写法介绍
2020/06/15 Python
python求解汉诺塔游戏
2020/07/09 Python
Linux安装Python3如何和系统自带的Python2并存
2020/07/23 Python
菲律宾最大的网上花店和礼品店:PhilFlower.com
2018/02/09 全球购物
BLACKMORES澳洲官网:澳大利亚排名第一的保健品牌
2018/09/27 全球购物
英语专业职业生涯规划范文
2014/03/05 职场文书
说明书怎么写
2014/05/06 职场文书
交通文明倡议书
2014/05/16 职场文书
高考标语大全
2014/06/05 职场文书
贫困证明模板(3篇)
2014/09/16 职场文书
公司收款委托书范本
2014/09/20 职场文书
2014年转正工作总结
2014/11/08 职场文书
小学班级管理心得体会
2016/01/07 职场文书
4种非常实用的python内置数据结构
2021/04/28 Python
SQL 窗口函数实现高效分页查询的案例分析
2021/05/21 SQL Server
MySQL详细讲解变量variables的用法
2022/06/21 MySQL