parent
617406cbbf
commit
f5f1c4e0b0
|
@ -1,14 +1,11 @@
|
||||||
services:
|
services:
|
||||||
favicon:
|
favicon-api:
|
||||||
image: favicon-api:latest
|
image: favicon-api:latest
|
||||||
container_name: favicon-api
|
container_name: favicon-api
|
||||||
ports:
|
ports:
|
||||||
- 8001:8000
|
- 8001:8000
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
REDIS_URL: redis://redis:6379/0
|
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/share/zoneinfo/Asia/Shanghai:/usr/share/zoneinfo/Asia/Shanghai:ro
|
- /usr/share/zoneinfo/Asia/Shanghai:/usr/share/zoneinfo/Asia/Shanghai:ro
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
@ -16,18 +13,4 @@ services:
|
||||||
- ./data:/app/data:rw
|
- ./data:/app/data:rw
|
||||||
- ./conf:/app/conf:rw
|
- ./conf:/app/conf:rw
|
||||||
- ./logs:/app/logs:rw
|
- ./logs:/app/logs:rw
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
|
||||||
- favicon_network
|
|
||||||
depends_on:
|
|
||||||
- redis
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: favicon-redis
|
|
||||||
networks:
|
|
||||||
- favicon_network
|
|
||||||
|
|
||||||
networks:
|
|
||||||
favicon_network:
|
|
||||||
driver: bridge
|
|
|
@ -7,7 +7,6 @@ from typing import Tuple, Optional
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
import setting
|
import setting
|
||||||
from favicon_app.asyncs import redis_pool
|
|
||||||
from favicon_app.models import favicon
|
from favicon_app.models import favicon
|
||||||
from favicon_app.utils import header
|
from favicon_app.utils import header
|
||||||
from favicon_app.utils.filetype import helpers, filetype
|
from favicon_app.utils.filetype import helpers, filetype
|
||||||
|
@ -136,7 +135,6 @@ class FaviconAsync(favicon.Favicon):
|
||||||
content = await resp.read()
|
content = await resp.read()
|
||||||
return content, ct_type
|
return content, ct_type
|
||||||
else:
|
else:
|
||||||
await redis_pool.set_cache(domain, setting.time_of_7_days, setting.time_of_7_days)
|
|
||||||
favicon.failed_url_cache(domain, setting.time_of_7_days)
|
favicon.failed_url_cache(domain, setting.time_of_7_days)
|
||||||
logger.error('异步请求失败: %d, URL: %s', resp.status, url)
|
logger.error('异步请求失败: %d, URL: %s', resp.status, url)
|
||||||
break
|
break
|
||||||
|
@ -148,7 +146,6 @@ class FaviconAsync(favicon.Favicon):
|
||||||
logger.warning('异步请求超时,正在重试(%d/%d): %s', retry_count, retries, url)
|
logger.warning('异步请求超时,正在重试(%d/%d): %s', retry_count, retries, url)
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await redis_pool.set_cache(domain, setting.time_of_7_days, setting.time_of_7_days)
|
|
||||||
favicon.failed_url_cache(domain, setting.time_of_7_days)
|
favicon.failed_url_cache(domain, setting.time_of_7_days)
|
||||||
logger.error('异步请求异常: %s, URL: %s', str(e), url)
|
logger.error('异步请求异常: %s, URL: %s', str(e), url)
|
||||||
break
|
break
|
||||||
|
|
|
@ -60,7 +60,7 @@ class FaviconServiceAsync(favicon_service.FaviconService):
|
||||||
|
|
||||||
strategy_url, strategy_name = strategy()
|
strategy_url, strategy_name = strategy()
|
||||||
if strategy_url is not None:
|
if strategy_url is not None:
|
||||||
logger.debug(f"-> 异步尝试从 {strategy_name} 获取图标")
|
logger.info(f"-> 异步尝试从 {strategy_name} 获取图标")
|
||||||
icon_content, icon_type = await entity.async_get_icon_file(strategy_url, strategy_url == '')
|
icon_content, icon_type = await entity.async_get_icon_file(strategy_url, strategy_url == '')
|
||||||
|
|
||||||
# 图标获取失败,或图标不是支持的图片格式,写入默认图标
|
# 图标获取失败,或图标不是支持的图片格式,写入默认图标
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from typing import AsyncGenerator
|
|
||||||
|
|
||||||
from fastapi import Depends
|
|
||||||
from redis.asyncio import ConnectionPool, Redis
|
|
||||||
|
|
||||||
import setting
|
|
||||||
|
|
||||||
REDIS_URL = setting.REDIS_URL
|
|
||||||
|
|
||||||
pool = ConnectionPool.from_url(
|
|
||||||
REDIS_URL,
|
|
||||||
max_connections=200,
|
|
||||||
decode_responses=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_redis() -> AsyncGenerator[Redis, None]:
|
|
||||||
async with Redis(connection_pool=pool) as conn:
|
|
||||||
yield conn
|
|
||||||
|
|
||||||
|
|
||||||
async def set_cache(
|
|
||||||
key: str,
|
|
||||||
value: str,
|
|
||||||
ttl: int | None = None,
|
|
||||||
r: Redis = Depends(get_redis),
|
|
||||||
):
|
|
||||||
await r.set(key, value, ex=ttl)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_cache(key: str, r: Redis = Depends(get_redis)):
|
|
||||||
return await r.get(key)
|
|
||||||
|
|
||||||
|
|
||||||
async def del_cache(key: str, r: Redis = Depends(get_redis)):
|
|
||||||
await r.delete(key)
|
|
14
main.py
14
main.py
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from contextlib import asynccontextmanager
|
|
||||||
|
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.responses import Response
|
from fastapi.responses import Response
|
||||||
|
|
||||||
import setting
|
import setting
|
||||||
from favicon_app.asyncs.redis_pool import pool
|
|
||||||
from favicon_app.routes import favicon_router
|
from favicon_app.routes import favicon_router
|
||||||
from favicon_app.utils.file_util import FileUtil
|
from favicon_app.utils.file_util import FileUtil
|
||||||
|
|
||||||
|
@ -23,18 +21,8 @@ default_icon_file = setting.default_icon_file
|
||||||
# referer日志文件路径
|
# referer日志文件路径
|
||||||
referer_log_file = setting.referer_log_file
|
referer_log_file = setting.referer_log_file
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
|
||||||
async def lifespan(app: FastAPI):
|
|
||||||
"""应用级生命周期:启动/清理。"""
|
|
||||||
print("Redis pool ready.")
|
|
||||||
yield
|
|
||||||
await pool.aclose()
|
|
||||||
print("Redis pool closed.")
|
|
||||||
|
|
||||||
|
|
||||||
# fastapi
|
# fastapi
|
||||||
app = FastAPI(lifespan=lifespan, title="Favicon API", description="获取网站favicon图标", version="3.0")
|
app = FastAPI(title="Favicon API", description="获取网站favicon图标", version="3.0.0")
|
||||||
app.include_router(favicon_router)
|
app.include_router(favicon_router)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
--index https://mirrors.xinac.net/pypi/simple
|
--index https://mirrors.xinac.net/pypi/simple
|
||||||
--extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple
|
--extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
|
||||||
fastapi~=0.116
|
fastapi~=0.116.1
|
||||||
pydantic~=2.11
|
pydantic~=2.11.7
|
||||||
pydantic_core~=2.33
|
pydantic_core~=2.33.2
|
||||||
starlette~=0.47
|
starlette~=0.47.3
|
||||||
requests~=2.32
|
requests~=2.32.5
|
||||||
aiohttp~=3.12
|
aiohttp~=3.12.15
|
||||||
bs4~=0.0
|
bs4~=0.0.2
|
||||||
beautifulsoup4~=4.13
|
beautifulsoup4~=4.13.5
|
||||||
lxml~=6.0
|
lxml~=6.0.1
|
||||||
PyYAML~=6.0
|
PyYAML~=6.0.2
|
||||||
uvicorn~=0.35
|
uvicorn~=0.35.0
|
||||||
uvicorn-worker~=0.3
|
uvicorn-worker~=0.3.0
|
||||||
gunicorn~=23.0
|
gunicorn~=23.0.0
|
||||||
redis[hiredis]~=6.4
|
|
||||||
|
|
|
@ -39,4 +39,3 @@ time_of_30_days = 30 * time_of_1_days
|
||||||
|
|
||||||
# 是否使用同步方式
|
# 是否使用同步方式
|
||||||
sync = 'false'
|
sync = 'false'
|
||||||
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")
|
|
||||||
|
|
Loading…
Reference in New Issue