add 站点图标缓存

This commit is contained in:
jxxghp 2023-06-12 09:00:59 +08:00
parent 7345cd237e
commit 6e8b687545
4 changed files with 86 additions and 34 deletions

View File

@ -1,4 +1,8 @@
from typing import Tuple import base64
from typing import Tuple, Optional
from urllib.parse import urljoin
from lxml import etree
from app.chain import ChainBase from app.chain import ChainBase
from app.core.config import settings from app.core.config import settings
@ -6,6 +10,7 @@ from app.db.sites import Sites
from app.helper.cookiecloud import CookieCloudHelper from app.helper.cookiecloud import CookieCloudHelper
from app.helper.sites import SitesHelper from app.helper.sites import SitesHelper
from app.log import logger from app.log import logger
from app.utils.http import RequestUtils
class CookieCloudChain(ChainBase): class CookieCloudChain(ChainBase):
@ -36,20 +41,59 @@ class CookieCloudChain(ChainBase):
_update_count = 0 _update_count = 0
_add_count = 0 _add_count = 0
for domain, cookie in cookies.items(): for domain, cookie in cookies.items():
if self.sites.exists(domain):
# 更新站点Cookie
self.sites.update_cookie(domain, cookie)
_update_count += 1
else:
# 获取站点信息 # 获取站点信息
indexer = self.siteshelper.get_indexer(domain) indexer = self.siteshelper.get_indexer(domain)
if indexer: if self.sites.exists(domain):
# 更新站点Cookie
self.sites.update_cookie(domain=domain, cookies=cookie)
_update_count += 1
elif indexer:
# 新增站点 # 新增站点
self.sites.add(name=indexer.get("name"), self.sites.add(name=indexer.get("name"),
url=indexer.get("domain"), url=indexer.get("domain"),
domain=domain, domain=domain,
cookie=cookie) cookie=cookie)
_add_count += 1 _add_count += 1
# 保存站点图标
if indexer:
icon_url, icon_base64 = self.__parse_favicon(url=indexer.get("domain"),
cookie=cookie,
ua=settings.USER_AGENT)
if icon_url:
self.sites.update_icon(name=indexer.get("name"),
domain=domain,
icon_url=icon_url,
icon_base64=icon_base64)
# 处理完成
ret_msg = f"更新了{_update_count}个站点,新增了{_add_count}个站点" ret_msg = f"更新了{_update_count}个站点,新增了{_add_count}个站点"
logger.info(f"CookieCloud同步成功{ret_msg}") logger.info(f"CookieCloud同步成功{ret_msg}")
return True, ret_msg return True, ret_msg
@staticmethod
def __parse_favicon(url: str, cookie: str, ua: str) -> Tuple[str, Optional[str]]:
"""
解析站点favicon,返回base64 fav图标
:param url: 站点地址
:param cookie: Cookie
:param ua: User-Agent
:return:
"""
favicon_url = urljoin(url, "favicon.ico")
res = RequestUtils(cookies=cookie, timeout=60, ua=ua).get_res(url=url)
if res:
html_text = res.text
else:
logger.error(f"获取站点页面失败:{url}")
return favicon_url, None
html = etree.HTML(html_text)
if html:
fav_link = html.xpath('//head/link[contains(@rel, "icon")]/@href')
if fav_link:
favicon_url = urljoin(url, fav_link[0])
res = RequestUtils(cookies=cookie, timeout=20, ua=ua).get_res(url=favicon_url)
if res:
return favicon_url, base64.b64encode(res.content).decode()
else:
logger.error(f"获取站点图标失败:{favicon_url}")
return favicon_url, None

View File

@ -35,3 +35,18 @@ class Site(Base):
@staticmethod @staticmethod
def get_actives(db: Session): def get_actives(db: Session):
return db.query(Site).filter(Site.is_active == 1).all() return db.query(Site).filter(Site.is_active == 1).all()
class SiteIcon(Base):
"""
站点图标表
"""
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
name = Column(String, nullable=False)
domain = Column(String, index=True)
url = Column(String, nullable=False)
base64 = Column(String)
@staticmethod
def get_by_domain(db: Session, domain: str):
return db.query(SiteIcon).filter(SiteIcon.domain == domain).first()

View File

@ -3,7 +3,7 @@ from typing import Tuple, List
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import SessionLocal from app.db import SessionLocal
from app.db.models.site import Site from app.db.models.site import Site, SiteIcon
class Sites: class Sites:
@ -60,3 +60,17 @@ class Sites:
"cookie": cookies "cookie": cookies
}) })
return True, "更新站点Cookie成功" return True, "更新站点Cookie成功"
def update_icon(self, name: str, domain: str, icon_url: str, icon_base64: str) -> bool:
"""
更新站点图标
"""
siteicon = SiteIcon(name=name, domain=domain, url=icon_url, base64=icon_base64)
if not siteicon.get_by_domain(self._db, domain):
siteicon.create(self._db)
elif icon_base64:
siteicon.update(self._db, {
"url": icon_url,
"base64": f"data:image/ico;base64,{icon_base64}"
})
return True

View File

@ -38,7 +38,6 @@ class ISiteUserInfo(metaclass=ABCMeta):
# 站点信息 # 站点信息
self.site_name = None self.site_name = None
self.site_url = None self.site_url = None
self.site_favicon = None
# 用户信息 # 用户信息
self.username = None self.username = None
self.userid = None self.userid = None
@ -92,8 +91,6 @@ class ISiteUserInfo(metaclass=ABCMeta):
self.site_name = site_name self.site_name = site_name
self.site_url = url self.site_url = url
self._base_url = f"{split_url.scheme}://{split_url.netloc}" self._base_url = f"{split_url.scheme}://{split_url.netloc}"
self._favicon_url = urljoin(self._base_url, "favicon.ico")
self.site_favicon = ""
self._site_cookie = site_cookie self._site_cookie = site_cookie
self._index_html = index_html self._index_html = index_html
self._session = session if session else requests.Session() self._session = session if session else requests.Session()
@ -123,7 +120,6 @@ class ISiteUserInfo(metaclass=ABCMeta):
解析站点信息 解析站点信息
:return: :return:
""" """
self._parse_favicon(self._index_html)
if not self._parse_logged_in(self._index_html): if not self._parse_logged_in(self._index_html):
return return
@ -197,23 +193,6 @@ class ISiteUserInfo(metaclass=ABCMeta):
""" """
pass pass
def _parse_favicon(self, html_text: str):
"""
解析站点favicon,返回base64 fav图标
:param html_text:
:return:
"""
html = etree.HTML(html_text)
if html:
fav_link = html.xpath('//head/link[contains(@rel, "icon")]/@href')
if fav_link:
self._favicon_url = urljoin(self._base_url, fav_link[0])
res = RequestUtils(cookies=self._site_cookie, session=self._session, timeout=60, headers=self._ua).get_res(
url=self._favicon_url)
if res:
self.site_favicon = base64.b64encode(res.content).decode()
def _get_page_content(self, url: str, params: dict = None, headers: dict = None): def _get_page_content(self, url: str, params: dict = None, headers: dict = None):
""" """
:param url: 网页地址 :param url: 网页地址