From a92dd232eee9a38d20157c8ba57773108220c639 Mon Sep 17 00:00:00 2001 From: jinql Date: Sat, 6 Sep 2025 14:59:02 +0800 Subject: [PATCH] 25.09.06 --- favicon_app/routes/favicon_routes.py | 2 +- favicon_app/routes/favicon_service.py | 72 ++++++++++++--------------- 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/favicon_app/routes/favicon_routes.py b/favicon_app/routes/favicon_routes.py index e81f0dd..d6ba8f0 100644 --- a/favicon_app/routes/favicon_routes.py +++ b/favicon_app/routes/favicon_routes.py @@ -33,7 +33,7 @@ async def get_favicon( bg_tasks: BackgroundTasks, url: Optional[str] = Query(None, description="网址:eg. https://www.baidu.com"), refresh: Optional[str] = Query(None, include_in_schema=False), - sync: Optional[str] = Query('true', description="是否使用同步方式获取") + sync: Optional[str] = Query('false', description="是否使用同步方式获取") ): """获取网站图标""" return await _service.get_favicon_handler(request, bg_tasks, url, refresh, sync) diff --git a/favicon_app/routes/favicon_service.py b/favicon_app/routes/favicon_service.py index 4a34016..ebeb394 100644 --- a/favicon_app/routes/favicon_service.py +++ b/favicon_app/routes/favicon_service.py @@ -37,9 +37,6 @@ class FaviconService: """图标服务类,封装所有与图标获取、缓存和处理相关的功能""" def __init__(self): - # 使用锁保证线程安全 - self._lock = Lock() - # 全局计数器和集合 self.url_count = 0 self.request_icon_count = 0 @@ -274,12 +271,11 @@ class FaviconService: icon_content = None try: - with self._lock: - if entity.domain in self.domain_list: - self._queue_pull(True, self.total_queue) - return _cached or default_icon_content - else: - self.domain_list.append(entity.domain) + if entity.domain in self.domain_list: + self._queue_pull(True, self.total_queue) + return _cached or default_icon_content + else: + self.domain_list.append(entity.domain) # 尝试从网站获取HTML内容 html_content = entity.req_get() @@ -333,31 +329,28 @@ class FaviconService: except Exception as e: logger.error(f"写入缓存文件失败: {e}") - with self._lock: - self.request_icon_count += 1 + self.request_icon_count += 1 return icon_content except Exception as e: logger.error(f"获取图标时发生错误 {entity.domain}: {e}") return _cached or default_icon_content finally: - with self._lock: - if entity.domain in self.domain_list: - self.domain_list.remove(entity.domain) - # 任务完成,从两个队列中移出元素 - self._queue_pull(True, self.icon_queue) - self._queue_pull(True, self.total_queue) + if entity.domain in self.domain_list: + self.domain_list.remove(entity.domain) + # 任务完成,从两个队列中移出元素 + self._queue_pull(True, self.icon_queue) + self._queue_pull(True, self.total_queue) def get_count(self) -> Dict[str, int]: """获取统计数据""" - with self._lock: - return { - 'url_count': self.url_count, - 'request_icon_count': self.request_icon_count, - 'request_cache_count': self.request_cache_count, - 'queue_size': self.icon_queue.qsize(), - 'total_queue_size': self.total_queue.qsize(), - } + return { + 'url_count': self.url_count, + 'request_icon_count': self.request_icon_count, + 'request_cache_count': self.request_cache_count, + 'queue_size': self.icon_queue.qsize(), + 'total_queue_size': self.total_queue.qsize(), + } async def get_favicon_handler( self, @@ -369,10 +362,9 @@ class FaviconService: ) -> dict[str, str] | Response: """处理获取图标的请求""" - logger.info(f"队列大小:{self.icon_queue.qsize()} | {self.total_queue.qsize()}") + logger.info(f"队列大小:{self.icon_queue.qsize()} | {self.total_queue.qsize()} | {len(favicon.failed_urls)}") - with self._lock: - self.url_count += 1 + self.url_count += 1 # 验证URL参数 if not url: @@ -387,13 +379,12 @@ class FaviconService: return self.get_default(self.time_of_7_days) # 检查内存缓存中的失败URL - with self._lock: - if entity.domain in favicon.failed_urls: - _expire_time = favicon.failed_urls[entity.domain] - if int(time.time()) <= _expire_time: - return self.get_default(self.time_of_7_days) - else: - del favicon.failed_urls[entity.domain] + if entity.domain in favicon.failed_urls: + _expire_time = favicon.failed_urls[entity.domain] + if int(time.time()) <= _expire_time: + return self.get_default(self.time_of_7_days) + else: + del favicon.failed_urls[entity.domain] # 检查缓存 _cached, cached_icon = self._get_cache_icon(entity.domain_md5, refresh=refresh in ['true', '1', 'True']) @@ -401,12 +392,11 @@ class FaviconService: if cached_icon: # 使用缓存图标 icon_content = cached_icon - with self._lock: - self.request_cache_count += 1 + self.request_cache_count += 1 # 确定内容类型和缓存时间 content_type = filetype.guess_mime(icon_content) if icon_content else "" - cache_time = self.time_of_1_hours * random.randint(1, 6) if self._is_default_icon_byte(icon_content) else self.time_of_7_days + cache_time = self.time_of_12_hours if self._is_default_icon_byte(icon_content) else self.time_of_7_days # 乐观缓存机制:检查缓存是否已过期但仍有缓存内容 # _cached 存在但 cached_icon 为 None 表示缓存已过期 @@ -422,10 +412,10 @@ class FaviconService: media_type=content_type if content_type else "image/x-icon", headers=self._get_header(content_type, cache_time)) else: + _referrer = request.headers.get('referrer') or request.headers.get('referer') # 检查sync参数 is_sync = sync in ['true', '1', 'True'] - - if not is_sync: + if (not is_sync) or (_referrer and not _referrer.startswith('https://api.xinac.net')): # 返回默认图片并加入后台队列 logger.info(f"返回默认图片并加入后台队列: {entity.domain}") # 开始图标处理,加入两个队列 @@ -458,7 +448,7 @@ class FaviconService: # 确定内容类型和缓存时间 content_type = filetype.guess_mime(icon_content) if icon_content else "" - cache_time = self.time_of_1_hours * random.randint(1, 6) if self._is_default_icon_byte(icon_content) else self.time_of_7_days + cache_time = self.time_of_12_hours if self._is_default_icon_byte(icon_content) else self.time_of_7_days return Response(content=icon_content, media_type=content_type if content_type else "image/x-icon",