
这几天查看统计的时候发现统计页面的小图标不显示了。

图标变成了一个白色方框,这个umami 一直无法加载 favicon,之前换成了:https://favicon.cccyun.cc/h4ck.org.cn
现在这个服务貌似证书过期了,也没人维护,看来也没多少人用啊:

本着能动手尽量别 bb 的理念,既然不能用了那就自建服务吧。
个人觉得最简单的代码还是通过 python 实现,依赖于 flask + favicon 库,只需要一百行代码就 ok 了。实现方式,通过 favicon 库获取图标,将图标数据缓存到 redis,再次请求直接返回 redis 缓存数据。完整代码如下:
from flask import Flask, request, redirect, jsonify
from urllib.parse import urlparse
rds = redis.Redis(host='localhost', port=6379, db=1)
def get_domain_from_url(url):
parsed_uri = urlparse(url)
return 'https://{uri.netloc}'.format(uri=parsed_uri)
count = int(rds.get(key))
count = int(rds.get(key))
def get_icon_list_from_rds(key):
js_str = json.dumps(icon_list)
rds.setex(key, 86400, js_str)
def hello_world(): # put application's code here
return ('--------------------------- <br> '
'Query count:' + str(get_query_count()) + '<br>'
'=========================== <br> '
'Baby Favicon Tool v1.0 \r\n<br> by:obaby \r\n <br><a href="https://oba.by" target="_blank">https://oba.by</a> <br>\r\r '
'<a href="https://h4ck.org.cn" target="_blank">https://h4ck.org.cn</a>')
# http://127.0.0.1:5000/api/get_favicon?url=https://h4ck.org.cn
@app.route('/api/get_favicon')
query = request.args.get('url')
if not query.startswith('http'):
query = 'http://' + query
icons = get_icon_list_from_rds(query)
# icons_str = json.dumps(icons)
@app.route('/api/redirect_favicon')
query = request.args.get('url')
if not query.startswith('http'):
query = 'http://' + query
icons = get_icon_list_from_rds(query)
icon_url = icons[0]['url']
icon_url = 'https://h4ck.org.cn/wp-content/uploads/2024/09/favicon.png'
return redirect(icon_url, code=302)
if __name__ == '__main__':
import json
from flask import Flask, request, redirect, jsonify
import favicon
import redis
import json
from urllib.parse import urlparse
app = Flask(__name__)
rds = redis.Redis(host='localhost', port=6379, db=1)
def get_domain_from_url(url):
parsed_uri = urlparse(url)
return 'https://{uri.netloc}'.format(uri=parsed_uri)
def get_query_count():
key = 'QUERY_COUNT'
count = 1
if rds.exists(key):
count = int(rds.get(key))
return count
def set_query_count():
key = 'QUERY_COUNT'
count = 1
if rds.exists(key):
count = int(rds.get(key))
count += 1
rds.set(key, count)
return count
def get_icon_list_from_rds(key):
if rds.exists(key):
# print('cached')
cashed = rds.get(key)
js = json.loads(cashed)
return js
icons = favicon.get(key)
# rds.set('url',icons,)
icon_list = []
for i in icons:
data = {
'url': i.url,
'width': i.width,
'height': i.height,
'format': i.format
}
icon_list.append(data)
js_str = json.dumps(icon_list)
rds.setex(key, 86400, js_str)
return icon_list
@app.route('/')
def hello_world(): # put application's code here
return ('--------------------------- <br> '
'Query count:' + str(get_query_count()) + '<br>'
'=========================== <br> '
'Baby Favicon Tool v1.0 \r\n<br> by:obaby \r\n <br><a href="https://oba.by" target="_blank">https://oba.by</a> <br>\r\r '
'<a href="https://h4ck.org.cn" target="_blank">https://h4ck.org.cn</a>')
# http://127.0.0.1:5000/api/get_favicon?url=https://h4ck.org.cn
@app.route('/api/get_favicon')
def search():
query = request.args.get('url')
if '.' not in query:
return 'invalid url'
if not query.startswith('http'):
query = 'http://' + query
icons = get_icon_list_from_rds(query)
set_query_count()
# icons_str = json.dumps(icons)
return jsonify(icons)
@app.route('/api/redirect_favicon')
def redirect_icon():
query = request.args.get('url')
if '.' not in query:
return 'invalid url'
if not query.startswith('http'):
query = 'http://' + query
set_query_count()
icons = get_icon_list_from_rds(query)
try:
icon_url = icons[0]['url']
except:
icon_url = 'https://h4ck.org.cn/wp-content/uploads/2024/09/favicon.png'
return redirect(icon_url, code=302)
if __name__ == '__main__':
app.run()
import json
from flask import Flask, request, redirect, jsonify
import favicon
import redis
import json
from urllib.parse import urlparse
app = Flask(__name__)
rds = redis.Redis(host='localhost', port=6379, db=1)
def get_domain_from_url(url):
parsed_uri = urlparse(url)
return 'https://{uri.netloc}'.format(uri=parsed_uri)
def get_query_count():
key = 'QUERY_COUNT'
count = 1
if rds.exists(key):
count = int(rds.get(key))
return count
def set_query_count():
key = 'QUERY_COUNT'
count = 1
if rds.exists(key):
count = int(rds.get(key))
count += 1
rds.set(key, count)
return count
def get_icon_list_from_rds(key):
if rds.exists(key):
# print('cached')
cashed = rds.get(key)
js = json.loads(cashed)
return js
icons = favicon.get(key)
# rds.set('url',icons,)
icon_list = []
for i in icons:
data = {
'url': i.url,
'width': i.width,
'height': i.height,
'format': i.format
}
icon_list.append(data)
js_str = json.dumps(icon_list)
rds.setex(key, 86400, js_str)
return icon_list
@app.route('/')
def hello_world(): # put application's code here
return ('--------------------------- <br> '
'Query count:' + str(get_query_count()) + '<br>'
'=========================== <br> '
'Baby Favicon Tool v1.0 \r\n<br> by:obaby \r\n <br><a href="https://oba.by" target="_blank">https://oba.by</a> <br>\r\r '
'<a href="https://h4ck.org.cn" target="_blank">https://h4ck.org.cn</a>')
# http://127.0.0.1:5000/api/get_favicon?url=https://h4ck.org.cn
@app.route('/api/get_favicon')
def search():
query = request.args.get('url')
if '.' not in query:
return 'invalid url'
if not query.startswith('http'):
query = 'http://' + query
icons = get_icon_list_from_rds(query)
set_query_count()
# icons_str = json.dumps(icons)
return jsonify(icons)
@app.route('/api/redirect_favicon')
def redirect_icon():
query = request.args.get('url')
if '.' not in query:
return 'invalid url'
if not query.startswith('http'):
query = 'http://' + query
set_query_count()
icons = get_icon_list_from_rds(query)
try:
icon_url = icons[0]['url']
except:
icon_url = 'https://h4ck.org.cn/wp-content/uploads/2024/09/favicon.png'
return redirect(icon_url, code=302)
if __name__ == '__main__':
app.run()
到这里这个服务就算完成了,后续就是通过 nginx 反代了,经常反代的朋友都回了,我就不写了。
修改 umami 源代码:vim umami/src/components/common/Favicon.tsx

修改划线部分为上述内容,重新编译即可,编译过程中很可能会卡在 build-geo.修改 build 脚本 vim scripts/build-geo.js

这个破玩意儿 bug 之处在于,如果使用 github 代理,下载过程会出错,第二部分的实时解压就挂了,这个逻辑也是 tm 神了,不能下载完再解压吗?
直接下载第一处gz 文件解压,将 GeoLite2-City.mmdb放入geo 目录下,注释掉第二部分执行 yarn build 即可。不得不多,这 dq 真是给程序员创建了无数的便利,就尼玛离谱。重新启动服务一切就 ok 了。

图标又回来了,现有服务地址: https://favicon.h4ck.org.cn (不保证服务可用性,有时候的确是懒不想折腾了,之前的 gravatar 忽然因为 cdn 问题就失效了,结果删除重建也不行就放弃了。这个实属无奈,但是基本都会保证一个可用的服务。)
使用方法:
1. 获取 favicon 数据,返回 json 格式
http://127.0.0.1:5000/api/get_favicon?url=oba.by
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-300x300.png",
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-200x200.png",
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-200x200.png",
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-100x100.png",
"url": "https://oba.by/favicon.ico",
"url": "https://h4ck.org.cn/screenshots/obaby_tuya.jpg",
http://127.0.0.1:5000/api/redirect_favicon?url=oba.by
返回数据内容为上述接口的第一个结果,例如上面的 域名将会直接 302跳转到 https://oba.by/wp-content/uploads/2020/09/icon-500-300x300.png
如果没有 favicon 将会返回默认连接:https://h4ck.org.cn/wp-content/uploads/2024/09/favicon.png
接口:
1. 获取 favicon 数据,返回 json 格式
http://127.0.0.1:5000/api/get_favicon?url=oba.by
返回数据内容:
```json
[
{
"format": "png",
"height": 300,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-300x300.png",
"width": 300
},
{
"format": "png",
"height": 200,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-200x200.png",
"width": 200
},
{
"format": "png",
"height": 192,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-200x200.png",
"width": 192
},
{
"format": "png",
"height": 32,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-100x100.png",
"width": 32
},
{
"format": "ico",
"height": 0,
"url": "https://oba.by/favicon.ico",
"width": 0
},
{
"format": "jpg",
"height": 0,
"url": "https://h4ck.org.cn/screenshots/obaby_tuya.jpg",
"width": 0
}
]
```
2. 直接返回 favicon 链接
http://127.0.0.1:5000/api/redirect_favicon?url=oba.by
返回数据内容为上述接口的第一个结果,例如上面的 域名将会直接 302跳转到 https://oba.by/wp-content/uploads/2020/09/icon-500-300x300.png
如果没有 favicon 将会返回默认连接:https://h4ck.org.cn/wp-content/uploads/2024/09/favicon.png
接口:
1. 获取 favicon 数据,返回 json 格式
http://127.0.0.1:5000/api/get_favicon?url=oba.by
返回数据内容:
```json
[
{
"format": "png",
"height": 300,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-300x300.png",
"width": 300
},
{
"format": "png",
"height": 200,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-200x200.png",
"width": 200
},
{
"format": "png",
"height": 192,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-200x200.png",
"width": 192
},
{
"format": "png",
"height": 32,
"url": "https://oba.by/wp-content/uploads/2020/09/icon-500-100x100.png",
"width": 32
},
{
"format": "ico",
"height": 0,
"url": "https://oba.by/favicon.ico",
"width": 0
},
{
"format": "jpg",
"height": 0,
"url": "https://h4ck.org.cn/screenshots/obaby_tuya.jpg",
"width": 0
}
]
```
2. 直接返回 favicon 链接
http://127.0.0.1:5000/api/redirect_favicon?url=oba.by
返回数据内容为上述接口的第一个结果,例如上面的 域名将会直接 302跳转到 https://oba.by/wp-content/uploads/2020/09/icon-500-300x300.png
如果没有 favicon 将会返回默认连接:https://h4ck.org.cn/wp-content/uploads/2024/09/favicon.png
代码地址:
https://github.com/obaby/baby-favicon-tool.git
obaby
爱好广泛的火星小妖精,有问题欢迎留言交流啊~(✪ω✪)
爬虫类工具请先点击这个链接查看用法https://oba.by/?p=12240
闺蜜圈APP下载 https://guimiquan.cn
77 comments
我昨天想起来试一下你的 gravatar 发现打不开
g.obaby.blog 这个还是可以的,目前我用的是这个。那个不知道 cdn 怎么抽风了,死活不能回源。
亮丝和肉丝比,还是更爱灵妹妹的肉丝
这个是因为太阳反光了,并没有那么亮。
灵妹妹日更变周更了?
额。没想好写啥
就发发日常纪实、照片写真、丝袜秀都可以啊
哈哈!
前几天我也在折腾favicon,前、后台显示不一样,而follow里不显示,为了一个上图标,也折腾了一晚上。
这个东西,网上也找了几个地址,发现有的根本获取不到。
所以就自建了
用这个 https://unavatar.io/www.jeffer.xyz
这东西功能够丰富啊,然鹅

尴尬啦,好像有的上cdn没法获取。😂我用获取主体大部分都是海外。估计被防御挡住了。
应该不是cdn!我的可以获取哦
可能跟我的 cdn 策略有关系,国外默认开启防御,之前天天被 cc 攻击。
可能跟防御策略有关系,国外是默认开启的。不然老有沙雕来 cc
好方法,测试了一下,不但拿到了favicon,连封面图都能获取到。

啊。还有这个意外收获,这倒没注意。哈哈哈
姐的图片都是存哪的
又拍云被盗刷两百多都不敢用了 
图片就在服务器上扔着,套了个带防御的 cdn,我目前用的 https://scdn.ddunyun.com/#/dashboard
晓得了
之前看到好多开源php版本的,还是有些图片获取不到,get了。👍
我记得前一段你写了个好物推荐页面的文章,怎么没找到啊?
你说的是这个东西吗?https://h4ck.org.cn/my-devices
就是这个,我记得你发过源码的那篇文章。
this one https://h4ck.org.cn/2024/07/17545
扫得斯乃,谢谢钟妹,我搜索搜错关键词了。
这种一般搜索 抄作业,😂
有技术的就是厉害呀,一言不合就自己开干
主要是站在巨人的肩上,确实没啥难度,哈哈哈
我也是一言不合就开始改,不过还是太懒啦,怎么简单怎么来
一百来行代码能解决的就干,超过一千行就想放弃了。😂
我一直以为不显示图标是没开梯子的缘故

umami自带的是需要开梯子的(用的 duckduckgo 的https://icons.duckduckgo.com/ip3/),后来我给换了,结果这个也挂了,就不如自建一个。
滴,打卡
滴 老年卡
滴,学生卡
动手能力真强啊
雕虫小技
额,我比较喜欢用PHP的。。
不会php
一个图标引发的
不可思议
主要吧,好多开放的借口效果不大行感觉
另一方面,就是你编程代码能力强哈。毫不费力的感觉。
不过我是docker部署的,懒得折腾啦!
umami好像就没显示过我站点头像
自己动手丰衣足食👍
是哒,奈何好多开放的借口不好用啊
国产程序员的特殊技能。
被逼无奈,😂
全干工程师
当时RSS朋友圈就是因为这个问题,走了捷径,调用{foto-1},回头再调回来

所以你也写了一个服务?
我找了下我之前的插件代码,gpt生成的,用了一个平台 ,应该是一个第三方的库。
评论等级显示图片没有哦!
哪个等级图片?
不懂就问,这玩意干嘛的?
为了获取网站小图标
仔细想了一下,貌似我没有服务用得上,单纯路过好了~
https://favicon.cccyun.cc/h4ck.org.cn我这打开后可以,且迅速关闭怕被误会
看来是证书更新了
厉害,厉害,技术女神,感觉会写代码的都很牛逼,那么会写代码的女神就更不简单了。哈哈
码农,码农而已
看来,我得给我的网站做一个“统计”页面了。
https://favicon.cccyun.cc/h4ck.org.cn
在课上打开了,幸亏没人看见
丝袜而已
好多评论,贴代码都能这么多层楼
欢迎盖楼
获取favicon太麻烦,我直接用图片代替,没有去用gravatar,用了国内团队替代的cravatar,但有的时候cravatar也会炸,也懒得折腾,能用就行
gravatar 目前我换成 weavatar 了,跟自建的共用。cravatar 更新延迟太严重了。
我不管 就是看不懂
不要在意这些细节😂
看到python脑壳就嗡嗡的。
我用的一为开发的getFavicon代码,PHP的比较适合我这类小白。
不过有些站点的ico图标不在根目录,就无法获取,这个问题我也头疼疼。
哈哈哈,python 多好啊。
这个可以获取到各种情况下的图标。
厉害,来学习学习