一段获取网站Favicon的PHP代码
闲来无事,网址收藏夹在图标上加一个网站图标.
参考: 网址收藏夹
主要流程:
- 获取链接域名
- 通过域名查找主站的
<link rel="icon" >
- 如果没找到寻找主域名+
favicon.ico
- 下载favicon图片到本地,第二次加载时只找本地图片.
- 如果域名不可访问,取域名的首字母生成icon图片
代码如下:
<?php
declare(strict_types=1);
define("ROOT_PATH", dirname(__FILE__, 2));
const ICON_PATH = ROOT_PATH.'/runtime/icons';
const FONT_PATH = ROOT_PATH.'/assets/font/';
/**
* @param string $sourceUrl 远程路径
* @param string $filename 本地路径
* @param $retry 重试次数
* @return string|null
*/
function downloadImg(string $sourceUrl, string $filename, $retry = 1){
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36';
$temp = $filename . '.tmp';
$resource = fopen($temp, 'w');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $sourceUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 60 * 24);
curl_setopt($ch, CURLOPT_FILE, $resource);
$httpCode = null;
while ($httpCode !== 200 && $retry > 0) {
$retry--;
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
}
$type = curl_getinfo($ch,CURLINFO_CONTENT_TYPE);
$result = null;
// 判断是否成功
if ($httpCode == 200 && str_contains($type,"image") ) {
$remoteSize = (float)curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD);
$localSize = (float)filesize($temp);
$abs = abs($localSize - $remoteSize);
if ($abs < 10 && $abs >= 0) {
$result = rename($temp, $filename) ? $filename : null;
}
}
curl_close($ch);
fclose($resource);
@unlink($temp);
return $result;
}
/**
* 读取图片
* @param $file
* @return void
*/
function readImg($file){
$info=getimagesize($file);
@ob_clean();
@ob_get_contents();
@ob_flush();
header('Content-Type: '.$info['mime']);
readfile($file);
}
function getFavicon($host) {
$ctx = stream_context_create([
'http' => [
'timeout' => 3
]
]);
$scheme='https://';
$preg=<<<REG
/<link[^>]*href="([^>|\"]*)"[\s]*rel="[^>|\"]*icon"[^>]*\/?>|<link[^>]*rel="[^>]*icon"[\s]*href="([^>|\"]*)"[^>]*\/?>/si
REG;
$icon="";
$url=$scheme.$host;
$fp = @fopen( $url, 'r' ,false,$ctx);
if(!$fp){
$scheme='http://';
$url=$scheme.$host;
$fp = @fopen( $url, 'r' ,false,$ctx);
}
if(!$fp){
return false;
}
while(!feof($fp)){
$line= fgets($fp);
preg_match($preg, $line, $match );
if($match && ($match[1]||$match[2])){
$icon=$match[1]?$match[1]:$match[2];
break;
}
if(str_contains($line, "/head>")){
break;
};
}
if(!$icon){
return false;
}
if(filter_var($icon,FILTER_VALIDATE_URL)){
return $icon;
}
if(strpos($icon,'//')===0){
$icon=str_replace("//",$scheme,$icon);
return $icon;
}
return $scheme.$host.$icon;
}
/**
*
* @param string $host
* @return
*/
function outFontIcon(string $host){
$hosts=explode('.',$host);
if(count($hosts)>2){
$text=$hosts[1];
}else{
$text=$hosts[0];
}
$randText=md5($host);
$bgRed=min(255,hexdec(substr($randText,0,2))+80);
$bgGreen=min(255,hexdec(substr($randText,16,2))+80);
$bgBlue=min(255,hexdec(substr($randText,-1,2))+80);
$text=ucfirst(substr($text,0,1));
$img = imagecreatetruecolor(128, 128);
$textcolor=imagecolorallocate($img, 0, 0, 0);
$bgColor=imagecolorallocate($img, $bgRed, $bgGreen, $bgBlue);
$font=realpath(FONT_PATH.'siyuan.ttf');
// imagecolortransparent($img,$bgColor);
imagefill($img,0,0,$bgColor);
// imagestring($img, 5, 0, 0, $text, $textcolor);
imagettftext($img, 80, 0, 25, 100, $textcolor, $font, $text);
@ob_clean();
header('Content-type: image/png');
imagepng($img);
imagedestroy($img);
}
$url=$_GET['u'];
$isURL=filter_var($url,FILTER_VALIDATE_URL);
$host=$url;
if($isURL){
$host= parse_url($url,PHP_URL_HOST);
}else{
$host= parse_url('http://'.$url,PHP_URL_HOST);
}
//$host="hi-arkin.com";
if(!is_dir(ICON_PATH) || !is_writable(ICON_PATH)){
mkdir(ICON_PATH,0755,true);
}
$iconFile=ICON_PATH.DIRECTORY_SEPARATOR.$host;
// 本地图片
if(file_exists($iconFile)){
readImg($iconFile);
die();
}
// ping
if(function_exists('fsockopen')) {
$ping = @fsockopen($host, 80, $errno, $errstr, 0.5);
if (!$ping) {
outFontIcon($host);
die();
}
fclose($ping);
}
// 获取官网图标
$icon = getFavicon($host);
if(!$icon){
$icon="http://".$host.'/favicon.ico';
}
// 下载图标
$icon=downloadImg($icon,$iconFile);
if($icon){
readImg($icon);
die();
}
// 直接域名英文
outFontIcon($host);
原作者:阿金
本文地址:https://hi-arkin.com/archives/favicon-php.html