halo自带的评论系统,集成了Gravatar头像服务,但是那个网站在国内存在连接问题,可能无法正常加载头像。如果不使用头像服务,评论的头像又会变得单调无趣。

那么…为什么不自己做一个头像服务api呢?

1、基本原理

Gravatar的原理是根据匿名用户提供的邮箱地址,GET请求/avatar/邮箱地址计算的哈希值,找到并返回对应的头像。

也就是说,只要我们把目标地址修改为自己的API接口,然后根据请求的哈希值返回相应头像即可。

原理非常简单,立马开干!

2、设计思路

为避免用户自主上传头像带来的不确定性和风险性,同时为了尽量保证用户使用中头像的一致性,所以稍微魔改一下判断逻辑。

预先准备0~36.webp,前端请求/avatar/hash后,简单根据哈希值末尾字符返回指定图片,如末尾为0,返回1.webp;末尾为a,返回11.webp。至于0.webp,用作处理错误请求情况下返回。

3、代码示例

本次使用的是flask以快速搭建一个简易的api接口。

from flask import Flask, send_file
from flask_cors import CORS
import string
import os

app = Flask(__name__)
CORS(app)
STATIC_DIR = 'static'
DEFAULT_AVATAR = '0.webp'  # 默认头像文件名

@app.route('/avatar/<path:hash_value>')
def get_avatar(hash_value):
    # 处理空路径或无字符的情况
    if not hash_value:
        return send_default_avatar()
    
    # 获取哈希值的尾字符(核心修改点:从首字符改为尾字符)
    last_char = hash_value[-1].lower()  # 用[-1]取最后一个字符
    
    # 处理数字 0-9(保持原逻辑)
    if last_char.isdigit():
        try:
            num = int(last_char) + 1  # 0 对应 1, 1 对应 2, ..., 9 对应 10
            if 1 <= num <= 10:
                return send_image(f"{num}.webp")
        except ValueError:
            pass
    
    # 处理字母 a-z(映射到 11-36)
    elif last_char in string.ascii_lowercase:
        try:
            # a 对应 11, b 对应 12, ..., z 对应 36
            num = string.ascii_lowercase.index(last_char) + 11
            return send_image(f"{num}.webp")
        except ValueError:
            pass
    
    # 其他情况返回默认头像
    return send_default_avatar()

def send_image(filename):
    file_path = os.path.join(STATIC_DIR, filename)
    if os.path.exists(file_path):
        return send_file(file_path, mimetype='image/webp')
    return send_default_avatar()

def send_default_avatar():
    default_path = os.path.join(STATIC_DIR, DEFAULT_AVATAR)
    if os.path.exists(default_path):
        return send_file(default_path, mimetype='image/webp')
    return "Avatar not found", 404

4、使用方法

生产环境推荐使用gunicorn部署flask项目

pip install flask flask-cors gunicorn #先安装所需环境

cd /app #导航到项目主文件所在位置

gunicorn -w 4 -b 0.0.0.0:8000 app:app #启动项目

参数说明:

  • -w 4:启动 4 个工作进程(Worker Processes),通常设置为 CPU 核心数 ×2+1

  • -b 0.0.0.0:8000:绑定到所有可用 IP 地址的 8000 端口

  • app:app:指定 WSGI 应用,格式为<模块名>:<Flask应用实例名>

    • 第一个app对应你的 Python 文件名(如果你的文件是app.py

    • 第二个app对应你在代码中创建的 Flask 实例app = Flask(__name__)

5、api接口

https://get-random-avatar.yuubari.cn/

使用示例:

https://get-random-avatar.yuubari.cn/avatar/hash

6、其他思路

最好的方式还是调用AI生成头像,并根据哈希值储存头像,后期遇相同哈希值直接调取头像即可,这种方式能够完全避免头像重复问题。