如何写长链接转短链接脚本

wen 实用脚本 25

本文目录导读:

如何写长链接转短链接脚本

  1. 基于数据库的自增ID方案
  2. 基于哈希的短链接生成
  3. 简单的命令行脚本
  4. API版本的短链接服务
  5. 使用方法

我来教你写一个长链接转短链接的脚本,提供几种常见的实现方式:

基于数据库的自增ID方案

Python实现

import hashlib
import string
import sqlite3
from datetime import datetime
class ShortURLGenerator:
    def __init__(self, db_path='short_urls.db'):
        self.conn = sqlite3.connect(db_path)
        self.cursor = self.conn.cursor()
        self.init_db()
    def init_db(self):
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS urls (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                long_url TEXT NOT NULL,
                short_code TEXT UNIQUE,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        self.conn.commit()
    def encode(self, num):
        """将数字转换为短码(62进制)"""
        chars = string.ascii_letters + string.digits  # a-z, A-Z, 0-9
        if num == 0:
            return chars[0]
        short_code = []
        while num > 0:
            num, remainder = divmod(num, 62)
            short_code.append(chars[remainder])
        return ''.join(reversed(short_code))
    def shorten(self, long_url):
        """生成短链接"""
        # 检查是否已存在
        self.cursor.execute('SELECT short_code FROM urls WHERE long_url = ?', (long_url,))
        result = self.cursor.fetchone()
        if result:
            return f"http://short.url/{result[0]}"
        # 插入新记录
        self.cursor.execute('INSERT INTO urls (long_url) VALUES (?)', (long_url,))
        self.conn.commit()
        # 获取自增ID并转换
        last_id = self.cursor.lastrowid
        short_code = self.encode(last_id)
        # 更新短码
        self.cursor.execute('UPDATE urls SET short_code = ? WHERE id = ?', (short_code, last_id))
        self.conn.commit()
        return f"http://short.url/{short_code}"
    def expand(self, short_url):
        """还原长链接"""
        short_code = short_url.split('/')[-1]
        self.cursor.execute('SELECT long_url FROM urls WHERE short_code = ?', (short_code,))
        result = self.cursor.fetchone()
        return result[0] if result else None
    def close(self):
        self.conn.close()
# 使用示例
if __name__ == "__main__":
    generator = ShortURLGenerator()
    # 生成短链接
    long_url = "https://www.example.com/very/long/url/that/needs/to/be/shortened"
    short_url = generator.shorten(long_url)
    print(f"长链接: {long_url}")
    print(f"短链接: {short_url}")
    # 还原长链接
    original_url = generator.expand(short_url)
    print(f"还原: {original_url}")
    generator.close()

基于哈希的短链接生成

import hashlib
import base64
class HashShortURLGenerator:
    def __init__(self, length=6):
        self.length = length
        self.url_map = {}
        self.collision_map = {}
    def generate_hash(self, long_url, salt=""):
        """生成短哈希码"""
        # 使用MD5生成哈希
        hash_input = long_url + salt
        md5_hash = hashlib.md5(hash_input.encode()).hexdigest()
        # 取前length位作为短码
        short_code = md5_hash[:self.length]
        return short_code
    def shorten(self, long_url):
        """生成短链接"""
        short_code = self.generate_hash(long_url)
        # 处理冲突
        counter = 0
        while short_code in self.url_map and self.url_map[short_code] != long_url:
            counter += 1
            short_code = self.generate_hash(long_url, str(counter))
        self.url_map[short_code] = long_url
        return f"http://short.url/{short_code}"
    def expand(self, short_url):
        """还原长链接"""
        short_code = short_url.split('/')[-1]
        return self.url_map.get(short_code)
# 使用示例
hash_generator = HashShortURLGenerator()
long_url = "https://www.example.com/very/long/url"
short_url = hash_generator.shorten(long_url)
print(f"哈希短链接: {short_url}")
print(f"还原: {hash_generator.expand(short_url)}")

简单的命令行脚本

#!/usr/bin/env python3
import sys
import hashlib
import json
import os
class SimpleShortURL:
    def __init__(self, data_file='short_urls.json'):
        self.data_file = data_file
        self.urls = self.load_data()
    def load_data(self):
        if os.path.exists(self.data_file):
            with open(self.data_file, 'r') as f:
                return json.load(f)
        return {}
    def save_data(self):
        with open(self.data_file, 'w') as f:
            json.dump(self.urls, f, indent=2)
    def generate_short_code(self):
        """生成8位随机短码"""
        import random
        import string
        chars = string.ascii_letters + string.digits
        return ''.join(random.choice(chars) for _ in range(8))
    def shorten(self, long_url):
        # 检查是否已存在
        for code, url in self.urls.items():
            if url == long_url:
                return code
        # 生成新短码
        short_code = self.generate_short_code()
        while short_code in self.urls:
            short_code = self.generate_short_code()
        self.urls[short_code] = long_url
        self.save_data()
        return short_code
    def expand(self, short_code):
        return self.urls.get(short_code)
def main():
    shortener = SimpleShortURL()
    if len(sys.argv) < 2:
        print("使用方法:")
        print(f"  {sys.argv[0]} shorten <长链接>  - 生成短链接")
        print(f"  {sys.argv[0]} expand <短码>     - 还原长链接")
        return
    command = sys.argv[1]
    if command == "shorten" and len(sys.argv) >= 3:
        long_url = sys.argv[2]
        short_code = shortener.shorten(long_url)
        print(f"短链接: http://short.url/{short_code}")
    elif command == "expand" and len(sys.argv) >= 3:
        short_code = sys.argv[2]
        long_url = shortener.expand(short_code)
        if long_url:
            print(f"长链接: {long_url}")
        else:
            print("未找到对应的长链接")
    else:
        print("无效命令")
if __name__ == "__main__":
    main()

API版本的短链接服务

# Flask版本的短链接服务API
from flask import Flask, request, jsonify, redirect
import hashlib
import string
from datetime import datetime
app = Flask(__name__)
# 内存存储(实际应用中应使用数据库)
url_store = {}
def generate_short_code(long_url, length=6):
    """生成短码"""
    hash_input = f"{long_url}{datetime.now().timestamp()}"
    md5_hash = hashlib.md5(hash_input.encode()).hexdigest()
    # 确保唯一性
    short_code = md5_hash[:length]
    while short_code in url_store:
        hash_input += "1"
        md5_hash = hashlib.md5(hash_input.encode()).hexdigest()
        short_code = md5_hash[:length]
    return short_code
@app.route('/shorten', methods=['POST'])
def shorten_url():
    """生成短链接API"""
    data = request.get_json()
    if not data or 'url' not in data:
        return jsonify({'error': '请提供url参数'}), 400
    long_url = data['url']
    # 检查是否已存在
    for code, url in url_store.items():
        if url == long_url:
            return jsonify({
                'short_url': f'/s/{code}',
                'long_url': long_url
            })
    # 生成新短链接
    short_code = generate_short_code(long_url)
    url_store[short_code] = {
        'long_url': long_url,
        'created_at': datetime.now().isoformat(),
        'clicks': 0
    }
    return jsonify({
        'short_url': f'/s/{short_code}',
        'long_url': long_url
    })
@app.route('/s/<short_code>')
def redirect_to_url(short_code):
    """短链接重定向"""
    url_data = url_store.get(short_code)
    if url_data:
        # 增加点击计数
        url_data['clicks'] += 1
        return redirect(url_data['long_url'])
    return jsonify({'error': '短链接不存在'}), 404
@app.route('/info/<short_code>')
def get_url_info(short_code):
    """获取短链接信息"""
    url_data = url_store.get(short_code)
    if url_data:
        return jsonify(url_data)
    return jsonify({'error': '短链接不存在'}), 404
if __name__ == '__main__':
    app.run(debug=True, port=5000)

使用方法

  1. 数据库版本:直接运行会创建SQLite数据库存储映射关系
  2. 哈希版本:简单的内存缓存,适合测试
  3. 命令行版本python short_url.py shorten "https://example.com/long-url"
  4. API版本:启动Flask服务后,POST请求到/shorten

选择哪种方案取决于你的具体需求:

  • 生产环境推荐数据库版本,可持久化存储
  • 简单使用推荐命令行版本
  • 微服务推荐API版本

抱歉,评论功能暂时关闭!