Home About Me

Generating a Visitor Info Image with PHP

I had some free time recently and saw someone building a little project like this, so I decided to make one too—and try to do it even better.

The idea is simple: use PHP to collect a visitor’s basic information, then draw that data onto a background image and output the final result directly as an image.

To make this work, the main external dependency is an IP geolocation API. After all, most people are not going to maintain their own IP database just for a small project like this.

What you need is straightforward:

  • one background image
  • one TTF font file
  • PHP with the required image functions enabled
  • Redis support if you want the visit counter to work as written

Here is the source code:

php //屏蔽错误提示(可以删掉) error_reporting(E_ALL^E_NOTICE^E_WARNING); //尝试多头部IP地址查询 function get_real_ip(){ static $realip; if(isset($_SERVER)){ if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ $realip=$_SERVER['HTTP_X_FORWARDED_FOR']; }else if(isset($_SERVER['HTTP_CLIENT_IP'])){ $realip=$_SERVER['HTTP_CLIENT_IP']; }else{ $realip=$_SERVER['REMOTE_ADDR']; } }else{ if(getenv('HTTP_X_FORWARDED_FOR')){ $realip=getenv('HTTP_X_FORWARDED_FOR'); }else if(getenv('HTTP_CLIENT_IP')){ $realip=getenv('HTTP_CLIENT_IP'); }else{ $realip=getenv('REMOTE_ADDR'); } } return $realip; } //获取City function getCity($ip) { $ch = curl_init(); $url = 'https://whois.pconline.com.cn/ipJson.jsp?ip='.$ip; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false ); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $location = curl_exec($ch); curl_close($ch); $location = mb_convert_encoding($location, 'utf-8','GB2312'); $location = substr($location, strlen('({')+strpos($location, '({'),(strlen($location) - strpos($location, '})'))*(-1)); $location = str_replace('"',"",str_replace(":","=",str_replace(",","&",$location))); parse_str($location,$ip_location); return $ip_location['addr']; } //获取系统 $_SERVER['HTTP_USER_AGENT']; $_SERVER['HTTP_ACCEPT_LANGUAGE']; function get_os() { if (!empty($_SERVER&['HTTP_USER_AGENT'])) { $os = $_SERVER&['HTTP_USER_AGENT']; if (preg_match('/win/i', $os)) { $os = 'Windows'; } else if (preg_match('/mac/i', $os)) { $os = 'MAC'; } else if (preg_match('/linux/i', $os)) { $os = 'Linux'; } else if (preg_match('/unix/i', $os)) { $os = 'Unix'; } else if (preg_match('/bsd/i', $os)) { $os = 'BSD'; } else { $os = 'Other'; } return $os; } else { return '未知'; } } $redis = new Redis(); $redis-connect('127.0.0.1', 6379); $check = $redis->exists("count"); if($check){ $redis->incr("count"); $count = $redis->get("count"); } //获取浏览器 function browse_info() { if (!empty($_SERVER['HTTP_USER_AGENT'])) { $br = $_SERVER['HTTP_USER_AGENT']; if (preg_match('/MSIE/i', $br)) { $br = 'MSIE'; } else if (preg_match('/Firefox/i', $br)) { $br = 'Firefox'; } else if (preg_match('/Chrome/i', $br)) { $br = 'Chrome'; } else if (preg_match('/Safari/i', $br)) { $br = 'Safari'; } else if (preg_match('/Maxthon/i', $br)) { $br = '遨游'; } else if (preg_match('/IE/i', $br)) { $br = 'IE'; } else if (preg_match('/Opera/i', $br)) { $br = 'Opera'; } else { $br = 'Other'; } return $br; } else { return 'unknow'; } } //获取运营商 function getIsp($ip) { $url="http://ip.taobao.com/service/getIpInfo.php?ip=".$ip; $ipinfo=json_decode(file_get_contents($url)); if($ipinfo->code==='1'){ return false; } $isp = $ipinfo->data->isp; return $isp; } //打开图片 $dst_path = 'yuantu.png';//原图,修改为你原图的路径 $dst = imagecreatefromstring(file_get_contents($dst_path)); $font = './XXX.ttf';//字体路径 //获取刚才生成的数据 $browse= browse_info(); $ip= get_real_ip(); $isp= getIsp($ip); $city=getCity("$ip"); $os=get_os(); $count0="$count 次"; //设定字体颜色 $black = imagecolorallocate($dst, 0x00, 0x00, 0x00);//字体颜色 //添加字体 imagefttext($dst,28,0,122,50,$black,$font,$ip); imagefttext($dst,26,0,151,102,$black,$font,$city); imagefttext($dst,28,0,155,153,$black,$font,$os); imagefttext($dst,28,0,181,205,$black,$font,$isp); imagefttext($dst,28,0,182,255,$black,$font,$browse); imagefttext($dst,28,0,182,302,$black,$font,$count0); //输出图片 list($dst_w, $dst_h, $dst_type) = getimagesize($dst_path); header('Content-Type: image/png'); imagepng($dst); imagedestroy($dst); ?>

The script does a few things in sequence:

  • tries several headers to get the visitor’s real IP
  • looks up the geographic location for that IP
  • detects the operating system from the User-Agent
  • identifies the browser
  • fetches the ISP information
  • optionally counts visits with Redis
  • writes all of that onto a base image using a TTF font
  • outputs the final PNG directly

A couple of points are worth noting.

For the location lookup, the code uses the whois.pconline.com.cn API and converts the returned data from GB2312 to utf-8 before parsing it. ISP information is retrieved separately through the Taobao IP interface.

The visit counter depends on Redis:

$redis = new Redis();
$redis-connect('127.0.0.1', 6379);
$check = $redis->exists("count");
if($check){
    $redis->incr("count");
    $count = $redis->get("count");
}

If your hosting environment does not support Redis, you will need to remove or modify that part.

The image generation itself is handled with PHP’s GD functions. The background image path is set with:

$dst_path = 'yuantu.png';

and the font path with:

$font = './XXX.ttf';

After the data is collected, imagefttext() places each line of text at fixed coordinates on the image. So if you want a different layout, you only need to replace the background image and adjust those positions.

Here is the preview:

Preview image