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中DOM方法的动态性
Apr 11 Python
使用Python的Twisted框架编写简单的网络客户端
Apr 16 Python
Python安装第三方库及常见问题处理方法汇总
Sep 13 Python
利用python获取当前日期前后N天或N月日期的方法示例
Jul 30 Python
python散点图实例之随机漫步
Aug 27 Python
对python csv模块配置分隔符和引用符详解
Dec 12 Python
Python多图片合并PDF的方法
Jan 03 Python
python3.4爬虫demo
Jan 22 Python
tensor和numpy的互相转换的实现示例
Aug 02 Python
python3.7将代码打包成exe程序并添加图标的方法
Oct 11 Python
python实现从wind导入数据
Dec 03 Python
使用Python文件读写,自定义分隔符(custom delimiter)
Jul 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
浅谈PHP中JSON数据操作
2015/07/01 PHP
最新版本PHP 7 vs HHVM 多角度比较
2016/02/14 PHP
基于PHP实现短信验证码接口(容联运通讯)
2016/09/06 PHP
PHP创建多级目录的两种方法
2016/10/28 PHP
PHP调用全国天气预报数据接口查询天气示例
2019/02/20 PHP
php array_map()函数实例用法
2021/03/03 PHP
js 学习笔记(三)
2009/12/29 Javascript
jquery利用event.which方法获取键盘输入值的代码
2011/10/09 Javascript
js日期联动示例
2014/05/02 Javascript
JavaScript中的6种运算符总结
2014/10/16 Javascript
jQuery支持动态参数将函数绑定到事件上的方法
2015/03/17 Javascript
JS实现控制表格单元格垂直对齐的方法
2015/03/30 Javascript
ECMAScript5(ES5)中bind方法使用小结
2015/05/07 Javascript
js实现获取当前时间是本月第几周的方法
2015/08/11 Javascript
jQuery在线选座位插件seat-charts特效代码分享
2015/08/27 Javascript
快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)
2016/08/29 Javascript
浅析js中mvvm模式实现的原理
2018/10/06 Javascript
Angular ui-roter 和AngularJS 通过 ocLazyLoad 实现动态(懒)加载模块和依赖
2018/11/25 Javascript
vue实现倒计时获取验证码效果
2020/04/17 Javascript
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
使用python调用浏览器并打开一个网址的例子
2014/06/05 Python
python脚本实现统计日志文件中的ip访问次数代码分享
2014/08/06 Python
python实现的希尔排序算法实例
2015/07/01 Python
Python Socket传输文件示例
2017/01/16 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
详解Python:面向对象编程
2019/04/10 Python
python 计算数据偏差和峰度的方法
2019/06/29 Python
使用pymysql查询数据库,把结果保存为列表并获取指定元素下标实例
2020/05/15 Python
python 进制转换 int、bin、oct、hex的原理
2021/01/13 Python
CSS3 Backgrounds属性相关介绍
2011/05/11 HTML / CSS
美国电子产品购物网站:BuyDig.com
2020/06/17 全球购物
新教师岗前培训方案
2014/06/05 职场文书
美术教师求职信范文
2015/03/20 职场文书
农民工工资承诺书大全
2015/05/04 职场文书
初二物理教学反思
2016/02/19 职场文书
详细聊聊vue中组件的props属性
2021/11/02 Vue.js