分享一个比较实用的网页favicon图标获取方法

希米  (UID: 5950) [复制链接]
帖子链接已复制到剪贴板
帖子已经有人评论啦,不支持删除!

723 6

不用再费劲去查源代码啦

正常是从源代码查找:

  • rel="icon"

  • rel="shortcut icon"

  • rel="apple-touch-icon"


等字符,但是有些网站可能并非是写入meta标签中而是动态生成,搜索不到的;

当无favicon图标地址时候直接用此方法就方便啦;

博客友链,导航站,这些用上 省事很多;

调用:

https://favicon.splitbee.io/?url=网页地址

 

例如:

https://favicon.splitbee.io/?url=https://www.dalao.net/

https://favicon.splitbee.io/?url=https://www.ximi.me/

博客:www.ximi.me
已有评论 ( 6 )
  • 头像
    希米 (UID: 5950)
    (博客:www.ximi.me)
    1楼
    tino https://ink.tino.im/api/content/links/fetch-metadata?url=dalao.net 支持

    不错,能开源嚒

  • 头像
    希米 (UID: 5950)
    (博客:www.ximi.me)
    2楼
    brynn 不错,能开源不

    用ai写了一个:

    例:

    https://i.ximi.me/logo.php?url=google.com

    代码:

    <?php
    /**
     * 仿 Splitbee Favicon 获取器
     * 用法: favicon.php?url=https://www.baidu.com
     */
    
    // 1. 获取并清理传入的 URL
    $target_url = isset($_GET['url']) ? trim($_GET['url']) : '';
    
    if (empty($target_url)) {
        header("HTTP/1.1 400 Bad Request");
        echo "Missing 'url' parameter.";
        exit;
    }
    
    // 确保 URL 带有协议头
    if (!preg_match("~^https?://~i", $target_url)) {
        $target_url = "http://" . $target_url;
    }
    
    // 解析出基础域名和 Scheme(用于后续拼接相对路径)
    $parsed_url = parse_url($target_url);
    if (!$parsed_url || !isset($parsed_url['host'])) {
        header("HTTP/1.1 400 Bad Request");
        echo "Invalid URL.";
        exit;
    }
    $base_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
    
    // 2. 初始化 cURL 用于请求
    function fetch_content($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);          // 设置超时
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 忽略SSL证书错误
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
        $data = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return [$data, $http_code];
    }
    
    $favicon_url = null;
    
    // 3. 步骤一:尝试抓取网页 HTML 并解析
    list($html, $code) = fetch_content($target_url);
    
    if ($code == 200 && !empty($html)) {
        // 使用 DOMDocument 解析 HTML,比正则更稳定
        $dom = new DOMDocument();
        // 禁用错误报错(防止 HTML 结构不规范弹出警告)
        libxml_use_internal_errors(true);
        $dom->loadHTML($html);
        libxml_clear_errors();
    
        $links = $dom->getElementsByTagName('link');
        foreach ($links as $link) {
            $rel = strtolower($link->getAttribute('rel'));
            // 匹配常见的 icon 关键词
            if (in_array($rel, ['icon', 'shortcut icon', 'apple-touch-icon'])) {
                $href = $link->getAttribute('href');
                if (!empty($href)) {
                    $favicon_url = $href;
                    break; // 找到第一个就跳出
                }
            }
        }
    }
    
    // 4. 步骤二:如果 HTML 中没找到,或者请求失败,尝试降级读取根目录下的 favicon.ico
    if (empty($favicon_url)) {
        $favicon_url = $base_url . '/favicon.ico';
    } else {
        // 5. 步骤三:补全相对路径
        if (substr($favicon_url, 0, 2) === '//') {
            $favicon_url = $parsed_url['scheme'] . ':' . $favicon_url;
        } elseif (substr($favicon_url, 0, 1) === '/') {
            $favicon_url = $base_url . $favicon_url;
        } elseif (!preg_match("~^https?://~i", $favicon_url)) {
            // 针对类似 "images/favicon.ico" 的相对路径
            $favicon_url = rtrim($target_url, '/') . '/' . ltrim($favicon_url, '/');
        }
    }
    
    // 6. 步骤四:请求真实的图标并输出
    list($icon_data, $icon_code) = fetch_content($favicon_url);
    
    if ($icon_code == 200 && !empty($icon_data)) {
        // 简单判断并设置图片响应头(也可以根据实际后缀或 mime 动态设置)
        if (strpos($favicon_url, '.png') !== false) {
            header('Content-Type: image/png');
        } elseif (strpos($favicon_url, '.svg') !== false) {
            header('Content-Type: image/svg+xml');
        } else {
            header('Content-Type: image/x-icon');
        }
        echo $icon_data;
    } else {
        // 如果连默认的也获取不到,可以返回一个你本地准备好的兜底透明图或默认图
        header('Content-Type: image/png');
        // 这里输出一个 1x1 的透明 PNG 或者是本地默认图标
        echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=');
    }
  • 头像
    希米 (UID: 5950)
    (博客:www.ximi.me)
    3楼
    tino https://ink.tino.im/api/content/links/fetch-metadata?url=dalao.net 支持

    你这个与我用ai写的这个算法上好像有点点区别,可能是获取优先级不一样;

     

    获取的图标不一样;

     

    https://i.ximi.me/logo.php?url=www.ximi.me

     

    https://ink.tino.im/api/content/links/fetch-metadata?url=www.ximi.me

  • 头像
    希米 (UID: 5950)
    (博客:www.ximi.me)
    4楼
    佳茗 记得之前坛里也有佬整过一个 favicon.im

    功能不错,但是广告太多太离谱了

  • 头像
    希米 (UID: 5950)
    (博客:www.ximi.me)
    5楼
    tino 可以让ai转写成php的 @Slf4j public class LinkUtils { private static final int TIMEOUT = 5000; private static ...

    根据你提供的代码转化好了

    logo:

    https://i.ximi.me/logo.php?url=www.ximi.me

    json:

    https://i.ximi.me/json.php?url=www.ximi.me

     

    代码如下:

    logo:

    <?php
    /**
     * 仿 Splitbee Favicon 获取器
     * 用法: favicon.php?url=https://www.baidu.com
     */
    
    // 1. 获取并清理传入的 URL
    $target_url = isset($_GET['url']) ? trim($_GET['url']) : '';
    
    if (empty($target_url)) {
        header("HTTP/1.1 400 Bad Request");
        echo "Missing 'url' parameter.";
        exit;
    }
    
    // 确保 URL 带有协议头
    if (!preg_match("~^https?://~i", $target_url)) {
        $target_url = "http://" . $target_url;
    }
    
    // 解析出基础域名和 Scheme(用于后续拼接相对路径)
    $parsed_url = parse_url($target_url);
    if (!$parsed_url || !isset($parsed_url['host'])) {
        header("HTTP/1.1 400 Bad Request");
        echo "Invalid URL.";
        exit;
    }
    $base_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
    
    // 2. 初始化 cURL 用于请求
    function fetch_content($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);          // 设置超时
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 忽略SSL证书错误
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
        $data = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return [$data, $http_code];
    }
    
    $favicon_url = null;
    
    // 3. 步骤一:尝试抓取网页 HTML 并解析
    list($html, $code) = fetch_content($target_url);
    
    if ($code == 200 && !empty($html)) {
        // 使用 DOMDocument 解析 HTML,比正则更稳定
        $dom = new DOMDocument();
        // 禁用错误报错(防止 HTML 结构不规范弹出警告)
        libxml_use_internal_errors(true);
        $dom->loadHTML($html);
        libxml_clear_errors();
    
        $links = $dom->getElementsByTagName('link');
        foreach ($links as $link) {
            $rel = strtolower($link->getAttribute('rel'));
            // 匹配常见的 icon 关键词
            if (in_array($rel, ['icon', 'shortcut icon', 'apple-touch-icon'])) {
                $href = $link->getAttribute('href');
                if (!empty($href)) {
                    $favicon_url = $href;
                    break; // 找到第一个就跳出
                }
            }
        }
    }
    
    // 4. 步骤二:如果 HTML 中没找到,或者请求失败,尝试降级读取根目录下的 favicon.ico
    if (empty($favicon_url)) {
        $favicon_url = $base_url . '/favicon.ico';
    } else {
        // 5. 步骤三:补全相对路径
        if (substr($favicon_url, 0, 2) === '//') {
            $favicon_url = $parsed_url['scheme'] . ':' . $favicon_url;
        } elseif (substr($favicon_url, 0, 1) === '/') {
            $favicon_url = $base_url . $favicon_url;
        } elseif (!preg_match("~^https?://~i", $favicon_url)) {
            // 针对类似 "images/favicon.ico" 的相对路径
            $favicon_url = rtrim($target_url, '/') . '/' . ltrim($favicon_url, '/');
        }
    }
    
    // 6. 步骤四:请求真实的图标并输出
    list($icon_data, $icon_code) = fetch_content($favicon_url);
    
    if ($icon_code == 200 && !empty($icon_data)) {
        // 简单判断并设置图片响应头(也可以根据实际后缀或 mime 动态设置)
        if (strpos($favicon_url, '.png') !== false) {
            header('Content-Type: image/png');
        } elseif (strpos($favicon_url, '.svg') !== false) {
            header('Content-Type: image/svg+xml');
        } else {
            header('Content-Type: image/x-icon');
        }
        echo $icon_data;
    } else {
        // 如果连默认的也获取不到,可以返回一个你本地准备好的兜底透明图或默认图
        header('Content-Type: image/png');
        // 这里输出一个 1x1 的透明 PNG 或者是本地默认图标
        echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=');
    }

    json:

    <?php
    // 1. 设置响应头为 JSON 格式
    header('Content-Type: application/json; charset=utf-8');
    
    // 2. 获取并清理 URL
    $target_url = isset($_GET['url']) ? trim($_GET['url']) : '';
    if (empty($target_url)) {
        echo json_encode([
            "status" => 400,
            "message" => "Bad Request",
            "devMessage" => "Missing 'url' parameter.",
            "data" => null
        ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }
    
    // 补全协议头
    if (!preg_match("~^https?://~i", $target_url)) {
        $target_url = "https://" . $target_url;
    }
    
    // 解析域名基础路径
    $parsed_url = parse_url($target_url);
    if (!$parsed_url || !isset($parsed_url['host'])) {
        echo json_encode([
            "status" => 400,
            "message" => "Bad Request",
            "devMessage" => "Invalid URL.",
            "data" => null
        ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }
    $base_url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
    
    // 3. 构造纯原生的请求环境(模拟浏览器)
    $context = stream_context_create([
        'http' => [
            'method' => 'GET',
            'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\r\n",
            'timeout' => 5,
            'follow_location' => 1,
            'ignore_errors' => true
        ],
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false,
        ]
    ]);
    
    // 4. 抓取网页 HTML
    $html = @file_get_contents($target_url, false, $context);
    
    // 初始化返回的 Data 结构 (对应你的 LinkInfoDTO)
    $data = [
        "url" => $target_url,
        "name" => "",
        "logo" => "",
        "description" => "",
        "charset" => "UTF-8" // 默认给 UTF-8
    ];
    
    if ($html) {
        // 5. 尝试从 Response Header 中或 HTML 中提取 Charset
        // 这里简单通过正则从 HTML 匹配 charset
        if (preg_match('/<meta[^>]+charset=["\']?([\w-]+)/i', $html, $matches)) {
            $data['charset'] = strtoupper($matches[1]);
        }
    
        // 6. 提取网站标题 Name (优先找 <title>,找不到找 og:title)
        if (preg_match('/<title>(.*?)<\/title>/is', $html, $matches)) {
            $data['name'] = trim($matches[1]);
        }
        if (empty($data['name'])) {
            if (preg_match('/<meta[^>]+(?:property|name)=["\'](?:og|twitter):title["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $matches)) {
                $data['name'] = trim($matches[1]);
            }
        }
    
        // 7. 用正则匹配 <link> 标签中的 icon / logo
        $favicon_url = '';
        if (preg_match('/<link[^>]+rel=["\'](?:shortcut )?icon["\'][^>]+href=["\']([^"\']+)["\']/i', $html, $matches)) {
            $favicon_url = $matches[1];
        } else {
            // 尝试匹配苹果设备高清图标
            if (preg_match('/<link[^>]+rel=["\']apple-touch-icon[^"\']*["\'][^>]+href=["\']([^"\']+)["\']/i', $html, $matches)) {
                $favicon_url = $matches[1];
            }
        }
    
        // 如果 HTML 没找到 logo,尝试找 og:image
        if (empty($favicon_url)) {
            if (preg_match('/<meta[^>]+(?:property|name)=["\'](?:og|twitter):image["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $matches)) {
                $favicon_url = $matches[1];
            }
        }
    
        // 8. 路径补全逻辑
        if (empty($favicon_url)) {
            $favicon_url = $base_url . '/favicon.ico';
        } else {
            if (substr($favicon_url, 0, 2) === '//') {
                $favicon_url = $parsed_url['scheme'] . ':' . $favicon_url;
            } elseif (substr($favicon_url, 0, 1) === '/') {
                $favicon_url = $base_url . $favicon_url;
            } elseif (!preg_match("~^https?://~i", $favicon_url)) {
                $favicon_url = rtrim($target_url, '/') . '/' . ltrim($favicon_url, '/');
            }
        }
        $data['logo'] = $favicon_url;
    
        // 9. 提取网站描述 Description
        if (preg_match('/<meta[^>]+(?:name|property)=["\'](?:description|og:description|twitter:description)["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $matches)) {
            $data['description'] = trim($matches[1]);
        }
    }
    
    // 10. 组装最终的目标 JSON 格式
    $result = [
        "status" => 200,
        "message" => "OK",
        "devMessage" => null,
        "data" => $data
    ];
    
    // 输出 JSON
    echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
  • 头像
    希米 (UID: 5950)
    (博客:www.ximi.me)
    6楼
    cjwlove 希米出品,必属精品。 期待开源

    代码就在楼上

域名市场
   域名载入中...
创建新帖
自助推广购买广告位
确认删除
确定要删除这篇帖子吗?删除后将无法恢复。
删除成功
帖子已成功删除,页面将自动刷新。
删除失败
删除帖子时发生错误,请稍后再试。