PHP favicon 获取接口:输入网址返回网站图标地址和图标文件 [复制链接]

一级用户组

很多 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'
最新回复

请先登录后再回复 登录

uid:4 一级用户组
关注
我与春风皆过客,你携秋水揽星河
发帖 20
评论 0
粉丝 0
关注 0
发新帖
目录
PHP favicon 获取接口:输入网址返回网站图标地址和图标文件