很多 API 平台都会提供网站图标获取接口。下面这份代码先尝试读取网页里的 icon 标签,再 fallback 到 /favicon.ico,并支持 JSON 返回或直接跳转。
<?php
declare(strict_types=1);
header('Access-Control-Allow-Origin: *');
function json_response(int $code, string $message, $data = null, int $status = 200): void
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(compact('code', 'message', 'data'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
function fetch_url(string $url): string
{
$context = stream_context_create([
'http' => [
'timeout' => 5,
'header' => "User-Agent: PHP-Favicon-API/1.0
",
],
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
],
]);
$html = @file_get_contents($url, false, $context);
return is_string($html) ? $html : '';
}
function absolutize(string $base, string $href): string
{
if (preg_match('#^https?://#i', $href)) {
return $href;
}
$parts = parse_url($base);
$origin = ($parts['scheme'] ?? 'https') . '://' . ($parts['host'] ?? '');
if (str_starts_with($href, '//')) {
return ($parts['scheme'] ?? 'https') . ':' . $href;
}
if (str_starts_with($href, '/')) {
return $origin . $href;
}
$path = rtrim(dirname($parts['path'] ?? '/'), '/');
return $origin . ($path ? $path . '/' : '/') . $href;
}
$site = trim((string)($_GET['url'] ?? ''));
if ($site === '') {
json_response(422, '缺少 url 参数', null, 422);
}
if (!preg_match('#^https?://#i', $site)) {
$site = 'https://' . $site;
}
if (!filter_var($site, FILTER_VALIDATE_URL)) {
json_response(422, 'url 格式错误', null, 422);
}
$html = fetch_url($site);
$icon = '';
if ($html !== '' && preg_match('/<link[^>]+rel=["'][^"']*(?:shortcut icon|icon|apple-touch-icon)[^"']*["'][^>]*>/i', $html, $m)) {
if (preg_match('/href=["']([^"']+)["']/i', $m[0], $hm)) {
$icon = absolutize($site, html_entity_decode($hm[1], ENT_QUOTES, 'UTF-8'));
}
}
if ($icon === '') {
$parts = parse_url($site);
$icon = ($parts['scheme'] ?? 'https') . '://' . ($parts['host'] ?? '') . '/favicon.ico';
}
if (($_GET['type'] ?? '') === 'redirect') {
header('Location: ' . $icon, true, 302);
exit;
}
json_response(0, 'ok', [
'site' => $site,
'favicon' => $icon,
]); 本地测试:
# 启动服务
php -S 127.0.0.1:8000 favicon-api.php
# JSON 返回
curl 'http://127.0.0.1:8000/favicon-api.php?url=example.com'
# 直接跳转到图标
curl -I 'http://127.0.0.1:8000/favicon-api.php?url=example.com&type=redirect'