ChatGPT免费站点 和 AIGC 工具导航
前一段写了一个AI工具导航 ,但是发现有些网站的favicon图标显示不出来(某外服务可显示,某内服务无法显示),于是就想办法解决这个问题。
favicon图标
导航网站制作上没什么技术难度,无非就是爬取一些网站的信息,然后列表展示出来。当然展示的时候,favicon图标是必不可少的,要不然就不好看了。
favicon图标是网站的标志,一般在浏览器的地址栏、标签页、书签栏等地方显示。一般是一个16×16, 32×32的小图标,通常存放在网站的根目录,图片格式是ico、png、svg等,名字常为favicon
、logo
等。
以下为favicon图标在HTML页面中声明:
< link rel = "icon" href = "https://www.baidu.com/favicon.ico" type = "image/x-icon" />
**注意,**我们应直接使用rel="icon"
,现在很多网站依然使用rel="shortcut icon"
,这是一种过时的用法,可以被淘汰掉了。
favicon除了使用线上地址,还支持base64格式内联,例如:
< link rel = "icon" href = "data:image/x-icon;base64,AAABAA...8AAA==" type = "image/x-icon" />
favicon图标显示方案
1. 使用 Favicon url
favicon图标不同于一般的图片素材,一般都不会有防盗链
的问题,所以我们可以直接使用线上地址。即:
< img src = "https://www.baidu.com/favicon.ico" />
所以,你在获取网站信息的时候,记得获取favicon图标的url,直接使用即可。
2. 存储 favicon 图标
如果你不想使用线上地址,那么你可以将网站favicon图标存储到你的服务器上,自己做映射。这样做的好处是,你可以将favicon图标存储到你的CDN上,统一管理。缺点是,你需要自己维护这些图标,当然,你可以使用一些工具来自动化处理。
当然,你也可以存储为base64格式,这样就不需要额外的存储空间了,就是网站数据文件会变大。
3. 使用第三方服务
如果你不想自己存储favicon图标,那么你可以使用第三方服务,例如:Google Shared Stuff (S2)、faviconkit.com、icons.duckduckgo.com等。
Google Shared Stuff (S2)
Google Shared Stuff (S2) 提供了一个统一形式 URL api服务,该 URL 可以自动提取相应网站的图标图像并返回。
其使用方法为 https://www.google.com/s2/favicons?domain=abc.com&sz=24
,您需要将 abc.com 替换为实际网站的域名。
如:https://www.google.com/s2/favicons?domain=blog.mzh.ren&sz=24
,就会返回我博客的favicon图标,直接通过<img>
标签引用即可。
faviconkit.com
faviconkit.com api:invisible-scarlet-centipede.faviconkit.com/{website}/{size}
,替换 website
为实际网站的域名,size
为图标大小。
如:https://invisible-scarlet-centipede.faviconkit.com/blog.mzh.ren/24
,就会返回我博客的favicon图标。
通过以上免费服务,我们可以获取到网站的favicon图标,但是这些api都是外网的,如果你的网站是内网,那么就无法使用了。我到现在还没找到一个内网的api服务,如果你知道,欢迎告诉我。
favicon图标批量获取
我导航网站的数量大概有900个,如果手动获取,那就太麻烦了,所以我写了一个脚本来自动获取,这样就省了很多时间。
puppeteer
方式
Puppeteer | Puppeteer
Puppeteer is a Node.js library which provides a high-level API to control Chrome/Chromium over the DevTools Protocol. Puppeteer runs in headless mode by default, but can be configured to run in full (“headful”) Chrome/Chromium.
puppeteer
是一个用于浏览器自动化的 Node.js 库,它提供了一组用来操纵Chrome的API。
2017年,谷歌公开发布了 Puppeteer,由 Chrome DevTools 团队开发,使其比其他类似项目具有重大优势,因为它得到了世界上使用最广泛的浏览器的同一家公司的机构支持。
具体操作步骤如下:
首先通过head请求检查网站是否有favicon图标,如果有,那么直接使用,否则进入下一步。
2.通过puppeteer
打开网站,然后获取网站的favicon图标地址。
如果这两步都失败了,就使用自己的默认图标。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
const http = require ( 'http' );
const https = require ( 'https' );
const fs = require ( 'fs' );
const puppeteer = require ( 'puppeteer' );
const { EventEmitter } = require ( 'events' )
EventEmitter . defaultMaxListeners = 20
const chatgptJson = require ( './chatgpt.json' );
const processFaviconUrl = async ( item ) => {
const url = item . url ;
const url_object = new URL ( url );
const website_url = url_object . protocol + "//" + url_object . host
const default_favicon_url = website_url + '/favicon.ico' ;
try {
console . log ( "check website url" )
const website_url_available = await checkURLAvailable ( website_url );
if ( ! website_url_available ) {
console . log ( 'website url not available' );
return item ;
}
} catch ( err ) {
console . log ( 'Error:' , err );
}
try {
console . log ( "check default favicon url" )
const default_favicon_url_available = await checkURLAvailable ( default_favicon_url );
console . log ( `The URL is ${ default_favicon_url_available ? 'valid' : 'invalid' } ` );
if ( default_favicon_url_available ) {
console . log ( 'has favicon' );
item . favicon = default_favicon_url ;
return item ;
}
} catch ( err ) {
console . error ( 'Error:' , err );
}
try {
console . log ( 'use puppeteer' );
const browser = await puppeteer . launch ({
headless : "new" ,
});
const page = await browser . newPage ();
await page . setDefaultNavigationTimeout ( 0 );
await page . goto ( item . url );
// get favicon
const favicon = await page . evaluate (() => {
const favicon = document . querySelector ( 'link[rel="icon"]' ) || document . querySelector ( 'link[rel="shortcut icon"]' );
return favicon ? favicon . href : null ;
});
console . log ( favicon );
if ( favicon ) {
item . favicon = favicon ;
console . log ( item );
}
await browser . close ();
return item ;
} catch ( err ) {
console . log ( err );
}
}
function checkURLAvailable ( url ) {
return new Promise (( resolve , reject ) => {
const protocol = url . startsWith ( 'https' ) ? https : http ;
protocol
. request ( url , { method : 'HEAD' }, ( res ) => {
if ( res . statusCode >= 200 && res . statusCode < 400 ) {
resolve ( true );
} else {
resolve ( false );
}
})
. on ( 'error' , ( err ) => {
reject ( err );
})
. end ();
});
}
Promise . all ( chatgptJson . map ( processFaviconUrl )). then (( results ) => {
fs . writeFileSync ( './chatgpt-new.json' , JSON . stringify ( results ));
console . log ( 'All done!' );
}). catch (( err ) => {
console . error ( err );
});
以上代码每次获取20-50个网站的favicon图标,多了就会卡死。我对异步和并发的一无所知,暂时没找到解决办法,哪位大佬发现了问题,欢迎指点一下,不胜感激。
playwright
方式
microsoft/playwright: Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
2020 年 1 月 31 日,微软发布Playwright。Playwright 在很多方面与 Puppeteer 非常相似。API 方法在大多数情况下是相同的,并且默认情况下 Playwright 还捆绑了兼容的浏览器。
Playwright 最大的区别在于跨浏览器支持。它可以驱动 Chromium、WebKit(Safari 的浏览器引擎)和 Firefox。
以下是使用playwright
获取favicon图标的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const fs = require ( 'fs' );
const { chromium } = require ( 'playwright' );
( async () => {
const data = fs . readFileSync ( 'chatgpt.json' );
const websites = JSON . parse ( data );
const browser = await chromium . launch ();
const context = await browser . newContext ();
for ( let website of websites ) {
const page = await context . newPage ();
try {
await page . goto ( website . url );
const faviconUrl = await page . $eval (
'link[rel="icon"]' ,
( el ) => el . href
) || page . $eval ( 'link[rel="shortcut icon"]' , ( el ) => el . href );
console . log ( `Favicon URL for ${ website . url } : ${ faviconUrl } ` );
website . favicon = faviconUrl ;
} catch ( err ) {
console . log ( err );
continue ;
}
await page . close ();
}
fs . writeFileSync ( 'chatgpt_new.json' , JSON . stringify ( websites ));
await context . close ();
await browser . close ();
})();
代码运行后,会在当前目录下生成chatgpt_new.json
文件,里面包含了所有网站的favicon图标地址。
以上代码一次性获取了所有网站的favicon图标,感觉playwright
比puppeteer
强壮一些,访问不了也不会卡死。(纯属个人感觉)
以上两段代码都是在ChatGPT的帮助下完成的,至于原理,我也不太清楚,请路过的大佬指点一下。
代码库
mzhren/favicon: get sites favicon by playwright and puppeteer
含有两种方式获取favicon图标的代码,以及 chatgpt站点数据 chatgpt.json
和 aigc站点数据 aigc.json
, 欢迎大家star。
参考资料