加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
app.py 10.96 KB
一键复制 编辑 原始数据 按行查看 历史
kanostar 提交于 2024-12-29 16:34 . 图片的修改
import textwrap
from datetime import datetime, timedelta
import random
import logging
from flask import Flask, send_file, make_response
from PIL import Image, ImageDraw, ImageFont, ImageOps
import io
import requests
import oss2
import yaml
import json
import os
import chinese_calendar
app = Flask(__name__)
# 获取图片的url
def get_image():
# 读取YAML配置文件
with open('resource/oss.yaml', 'r') as file:
config = yaml.safe_load(file)
oss_config = config['oss']
oss_access_key_id = oss_config['access_key_id']
oss_access_key_secret = oss_config['access_key_secret']
endpoint = oss_config['endpoint']
bucket_name = oss_config['bucket_name']
dir_name = oss_config['dir_name']
# 创建OSS客户端
auth = oss2.Auth(oss_access_key_id, oss_access_key_secret)
bucket = oss2.Bucket(auth, endpoint, bucket_name)
# 列举Bucket中的文件
def list_files(buckets, prefix):
for obj in oss2.ObjectIterator(buckets, prefix=prefix):
yield obj.key
# 获取文件列表
files = list(list_files(bucket, dir_name))[1:]
# 随机获取一个文件的key
random_key = random.choice(files)
return f'https://{bucket_name}.{endpoint}/{random_key}'
# 获取图片数据
def get_image_data(img_url):
response = requests.get(img_url)
if response.status_code == 200:
img = Image.open(io.BytesIO(response.content))
# 原始图片的宽度和高度
original_width, original_height = img.size
# 新的高度
new_height = 900
# 计算新的宽度,保持比例
new_width = int(original_width * new_height / original_height)
# 调整图片大小
resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
# 创建一个带有圆角的图片
mask = Image.new('L', resized_img.size, 0)
draw = ImageDraw.Draw(mask)
corner_radius = 20
draw.rounded_rectangle([(0, 0), resized_img.size], corner_radius, fill=255)
rounded_img = ImageOps.fit(resized_img, mask.size, centering=(0.5, 0.5))
rounded_img.putalpha(mask)
return rounded_img
else:
return "Image not found", 404
# 获取当今日期
def get_current_date():
today = datetime.now()
today_date = today.strftime("%Y-%m-%d")
weekdays = ["Mon.", "Tue.", "Wed.", "Thu.", "Fri.", "Sat.", "Sun."]
today_weekday = weekdays[today.weekday()]
return f"{today_date} {today_weekday}"
# 每日星座运势
def get_daily_star():
file_path = 'resource/stars.json'
stars = ["白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座",
"天蝎座", "射手座", "摩羯座", "水瓶座", "双鱼座"]
daily_star_url = f'https://api.leafone.cn/api/horoscope?name={random.choice(stars)}'
response = requests.get(daily_star_url)
if response.status_code == 200:
current_data = response.json()
with open(file_path, 'w', encoding='utf-8') as file:
current_data['data']['imageUrl'] = get_image()
json.dump(current_data['data'], file, ensure_ascii=False, indent=4)
return current_data['data']
elif response.status_code == 203:
logging.error("请求超过QPS限制:10 秒 1 次")
return "请求超过QPS限制:10 秒 1 次", 502
else:
logging.error("Failed to fetch daily text")
return "Failed to fetch daily text", 500
@app.route('/daily', methods=['GET'])
def image_with_text():
stars_file_path = f'resource/stars.json'
if not os.path.exists(stars_file_path):
os.makedirs(os.path.dirname(stars_file_path), exist_ok=True)
logging.error(f"文件{stars_file_path} 不存在", )
return "File not found", 404
try:
with open(stars_file_path, 'r', encoding='utf-8') as r:
already_data = json.load(r)
if datetime.now().strftime("%Y-%m-%d") in already_data.get('date', []):
best_star_json = already_data
image = get_image_data(best_star_json['imageUrl'])
else:
best_star_json = get_daily_star()
image = get_image_data(get_image())
except json.decoder.JSONDecodeError:
get_daily_star()
current_date = get_current_date() # 获取当前日期
horoscope = best_star_json['horoscope'] # 幸运星座
shorts = best_star_json['shorts'] # 概括
contentAll = best_star_json['contentAll'] # 说的话
luckyTime = best_star_json['lucklyTime'] # 时刻
# 计算各部分的高度
font_star = ImageFont.truetype("ttf/站酷高端黑修订版.ttf", 170)
font_medium = ImageFont.truetype("ttf/NotoSansSC-Bold.otf", 50)
font_date = ImageFont.truetype("ttf/NotoSansSC-Bold.otf", 60)
font_content = ImageFont.truetype("ttf/NotoSansSC-Bold.otf", 49)
horoscope_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), horoscope, font=font_star)
shorts_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), shorts, font=font_medium)
date_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), current_date, font=font_date)
luckyTime_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), luckyTime, font=font_medium)
contentAll_wrapped = textwrap.fill(contentAll, width=20)
contentAll_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), contentAll_wrapped,
font=font_content)
bottom_text_bbox = ImageDraw.Draw(Image.new('RGB', (1, 1))).textbbox((0, 0), "仅供娱乐|相信科学|请勿迷信",
font=font_medium)
total_height = (
horoscope_bbox[3] + # 幸运星座
(shorts_bbox[3] - shorts_bbox[1]) + # 概括
(date_bbox[3] - date_bbox[1]) + # 日期
(luckyTime_bbox[3] - luckyTime_bbox[1]) + # 时刻
(contentAll_bbox[3] - contentAll_bbox[1]) + # 说的话
image.height +
(bottom_text_bbox[3] - bottom_text_bbox[1]) + # 底部
250 # 横线
)
# 新建画布
canvas = Image.new('RGB', (1080, int(total_height)), color=(255, 255, 255))
draw = ImageDraw.Draw(canvas)
# 幸运星座
draw.text((40, 25), horoscope, font=font_star, fill=(0, 0, 0))
y_offset = horoscope_bbox[3] + 50
# 概括
draw.text((40, y_offset), shorts, font=font_medium, fill=(21, 155, 255))
y_offset += (shorts_bbox[3] - shorts_bbox[1])
# 日期
draw.text((600, 15), current_date, font=font_date, fill=(0, 0, 0))
y_offset += (date_bbox[3] - date_bbox[1])
# 时刻
draw.text((600, y_offset - 200), luckyTime, font=font_medium, fill=(239, 80, 150))
y_offset += (luckyTime_bbox[3] - luckyTime_bbox[1])
# 横线
draw.line([(40, y_offset - 30), (1050, y_offset - 30)], fill=(128, 128, 128), width=3)
y_offset += 20
# 说的话
draw.text((60, y_offset), contentAll_wrapped, font=font_content, fill=(0, 0, 0))
y_offset += (contentAll_bbox[3] - contentAll_bbox[1])
# 图片
canvas.paste(image, (70, int(y_offset + 100)), image)
y_offset += image.height
# 底部的话
draw.text((60, y_offset + 130), "仅供娱乐|相信科学|请勿迷信", font=font_medium, fill=(128, 128, 128))
y_offset += (bottom_text_bbox[3] - bottom_text_bbox[1])
# 竖线
draw.line([(20, 0), (20, total_height)], fill=(128, 128, 128), width=5)
# 将图片转换为字节流
img_byte_arr = io.BytesIO()
canvas.save(img_byte_arr, format='JPEG')
img_byte_arr = img_byte_arr.getvalue()
# 计算剩余时间直到午夜
now = datetime.now()
tomorrow = now + timedelta(days=1)
midnight = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 0, 0, 0)
seconds_until_midnight = (midnight - now).total_seconds()
response = make_response(send_file(io.BytesIO(img_byte_arr), mimetype='image/jpeg'))
response.headers['Cache-Control'] = f'public, max-age={int(seconds_until_midnight)}'
return response
# 获取节假日
def get_holidays():
start_year = datetime.now().date()
end_year = datetime(start_year.year + 1, start_year.month, start_year.day).date()
holidays = chinese_calendar.get_holidays(start_year, end_year)
vacation = {
None: "周末",
"New Year's Day": "元旦",
"Spring Festival": "春节",
"Tomb-sweeping Day": "清明节",
"Labour Day": "劳动节",
"Dragon Boat Festival": "端午节",
"National Day": "国庆节",
"Mid-autumn Festival": "中秋节"
}
result = {}
for holiday in holidays:
_, name = chinese_calendar.get_holiday_detail(holiday)
chinese_name = vacation.get(name, name)
days_diff = (holiday - start_year).days
if chinese_name not in result:
result[chinese_name] = days_diff
return result
@app.route('/holidays', methods=['GET'])
def image_with_holidays():
holidays = get_holidays()
year = datetime.now().year
month = datetime.now().month
today = datetime.now().day
# 新建画布
canvas = Image.new("RGB", (2480, 3508), color=(255, 255, 255))
draw = ImageDraw.Draw(canvas)
# 绘制背景图片
background = Image.open("img/2.png").resize((2480, 3508), Image.Resampling.LANCZOS)
canvas.paste(background, (0, 0))
# 设置字体
font_title = ImageFont.truetype("ttf/汉堡包手机字体.ttf", 100)
font_day = ImageFont.truetype("ttf/汉堡包手机字体.ttf", 250)
font_holiday = ImageFont.truetype("ttf/汉堡包手机字体.ttf", 90)
# 绘制日期
title = f"{year}{month}月"
title_x = 160
title_y = 70
draw.text((title_x, title_y), title, font=font_title, fill=(0, 0, 0))
day_text = f"{today}"
day_x = 270
day_y = 190
draw.text((day_x, day_y), day_text, font=font_day, fill=(0, 0, 0))
# 绘制节假日信息
holiday_x = 150
y_offset = day_y + 340
for i, (holiday_name, days_diff) in enumerate(holidays.items()):
# 构建节假日信息文本
if len(holiday_name) == 2:
holiday_name = f'{holiday_name[0]} {holiday_name[1]}'
holiday_text = f'{holiday_name} 快乐!' if days_diff == 0 else f"{holiday_name} {days_diff:3}天"
holiday_y = y_offset + i * 170
draw.text((holiday_x, holiday_y), holiday_text, font=font_holiday, fill=(0, 0, 0))
img_byte_arr = io.BytesIO()
canvas.save(img_byte_arr, format='JPEG')
img_byte_arr = img_byte_arr.getvalue()
# 计算剩余时间直到午夜
now = datetime.now()
tomorrow = now + timedelta(days=1)
midnight = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 0, 0, 0)
seconds_until_midnight = (midnight - now).total_seconds()
response = make_response(send_file(io.BytesIO(img_byte_arr), mimetype='image/jpeg'))
response.headers['Cache-Control'] = f'public, max-age={int(seconds_until_midnight)}'
return response
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, debug=True)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化