您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 如何利用Python打造短链服务
## 引言:短链服务的价值与市场需求
在信息爆炸的数字时代,短链服务已成为互联网基础设施的重要组成部分。根据统计,全球每天产生的短链转换超过50亿次,Twitter上约30%的推文包含短链。短链不仅能优化用户体验,还能:
1. 提升点击率(缩短的URL点击率比长URL高39%)
2. 便于社交媒体分享
3. 提供流量分析能力
4. 隐藏复杂的原始链接参数
本文将带领您使用Python构建一个完整的短链服务系统,涵盖从基础实现到高级功能的完整开发路径。
## 技术选型与架构设计
### 核心组件
- **Web框架**:FastAPI(高性能异步框架)
- **数据库**:Redis(高速键值存储)+ PostgreSQL(持久化存储)
- **短码生成算法**:Base62编码
- **部署方案**:Docker容器化
### 系统架构
用户请求 → Web服务器 → 短码解析 → 数据库查询 → 302重定向 ↑ ↓ API接口 ← 管理后台
## 基础实现步骤
### 1. 环境准备
```python
# 所需依赖
pip install fastapi uvicorn redis sqlalchemy python-multipart
import string
import hashlib
BASE62 = string.digits + string.ascii_letters
def generate_shortcode(url: str, length=6) -> str:
"""基于MD5哈希的Base62编码"""
md5 = hashlib.md5(url.encode()).hexdigest()
num = int(md5, 16)
shortcode = []
for _ in range(length):
num, rem = divmod(num, 62)
shortcode.append(BASE62[rem])
return ''.join(reversed(shortcode))
from sqlalchemy import Column, String, Integer, DateTime
from datetime import datetime
class ShortLink(Base):
__tablename__ = 'short_links'
id = Column(Integer, primary_key=True)
original_url = Column(String(2000), nullable=False)
short_code = Column(String(10), unique=True, index=True)
created_at = Column(DateTime, default=datetime.utcnow)
clicks = Column(Integer, default=0)
user_id = Column(Integer) # 多用户支持
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.post("/api/shorten")
async def create_shortlink(url: str):
# 校验URL格式
if not validators.url(url):
raise HTTPException(status_code=400, detail="Invalid URL")
# 生成短码(处理冲突)
while True:
code = generate_shortcode(url)
if not db.get(code): break
# 存储记录
db.insert({
"original_url": url,
"short_code": code,
"created_at": datetime.now()
})
return {"short_url": f"https://sho.rt/{code}"}
@app.get("/{code}")
async def redirect(code: str):
item = db.get(code)
if not item:
raise HTTPException(status_code=404)
# 更新点击统计
db.update_counter(code)
return RedirectResponse(item["original_url"])
def is_custom_code_available(code: str) -> bool:
"""检查自定义短码是否可用"""
return not db.exists(code) and len(code) >= 3
@app.post("/api/custom")
async def create_custom_link(url: str, code: str):
if not is_custom_code_available(code):
raise HTTPException(400, "Code not available")
...
class AnalyticsModel(Base):
__tablename__ = 'link_analytics'
id = Column(Integer, primary_key=True)
short_code = Column(String(10), index=True)
access_time = Column(DateTime)
referrer = Column(String(500))
user_agent = Column(String(500))
ip_address = Column(String(45))
def record_click(code: str, request: Request):
"""记录每次点击的详细信息"""
db.insert(AnalyticsModel(
short_code=code,
access_time=datetime.now(),
referrer=request.headers.get("referer"),
user_agent=request.headers.get("user-agent"),
ip_address=request.client.host
))
@app.post("/api/secure")
async def create_temporary_link(
url: str,
expires_in: int = None, # 过期秒数
password: str = None
):
record = {
"original_url": url,
"expires_at": datetime.now() + timedelta(seconds=expires_in) if expires_in else None,
"password": bcrypt.hashpw(password.encode(), bcrypt.gensalt()) if password else None
}
...
# 使用Redis作为一级缓存
redis = Redis(host='localhost', port=6379, db=0)
def get_shortlink(code: str):
# 先查Redis缓存
cached = redis.get(f"short:{code}")
if cached:
return json.loads(cached)
# 查数据库
item = db.query(code)
if item:
# 写入缓存,设置5分钟过期
redis.setex(f"short:{code}", 300, json.dumps(item))
return item
def pregenerate_codes(batch_size=1000):
"""预生成短码池减少实时计算压力"""
with db.transaction():
for _ in range(batch_size):
code = generate_random_code(6)
if not db.exists(code):
db.insert({"code": code, "status": "available"})
-- PostgreSQL优化示例
CREATE INDEX CONCURRENTLY idx_short_code ON short_links (short_code);
CREATE INDEX idx_created_at ON short_links (created_at);
from urllib.parse import urlparse
import dns.resolver
def is_malicious_url(url: str) -> bool:
domain = urlparse(url).netloc
try:
# 检查已知恶意域名列表
if domain in malicious_domains:
return True
# DNS黑名单检查
answers = dns.resolver.resolve(domain, 'A')
return any(str(ip) in blacklisted_ips for ip in answers)
except:
return False
from fastapi import Request
from fastapi.middleware import Middleware
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
@app.post("/api/shorten")
@limiter.limit("10/minute")
async def create_shortlink(request: Request, url: str):
...
version: '3'
services:
web:
build: .
ports:
- "8000:8000"
depends_on:
- redis
- postgres
redis:
image: redis:alpine
ports:
- "6379:6379"
postgres:
image: postgres:13
environment:
POSTGRES_PASSWORD: example
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
from prometheus_fastapi_instrumentator import Instrumentator
Instrumentator().instrument(app).expose(app)
关键监控指标: - 重定向延迟(P99 < 100ms) - 短链生成成功率 - 各短链点击量TOP 100 - 异常请求比例
shortener/
├── app/
│ ├── core/ # 核心逻辑
│ ├── models/ # 数据库模型
│ ├── routers/ # API路由
│ ├── static/ # 前端资源
│ └── main.py # 应用入口
├── tests/ # 单元测试
├── Dockerfile
├── requirements.txt
└── README.md
通过本文,您已经掌握了构建生产级短链服务的全套技术方案。进一步优化方向包括:
完整项目代码已托管在GitHub:[示例仓库链接]
“短链虽小,却能连接无限可能” —— 通过Python构建的短链服务,不仅是一项技术实践,更是理解现代Web架构的绝佳案例。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。