qq空间[神奇图片]的制作原理
发布于 1年前 作者 jackhu 669 次浏览

相信很多人都看到过qq空间转发的某条日志中有张神奇图片 会显示你的头像,个人qq等信息。很神奇的样子。我对这个有点兴趣,再加上我最近想学node,于是前天晚上开始从nodejs.org的主页hello,word开始学起。用了半天写出了这个简单的神奇图片 制作服务器。

首先是名词解释,允许我用度娘的链接HTTP_REFFER

通过referer的名词解释可以知道访问外部图片的时候会带上此次浏览的信息,那我们就去看看qq空间的referer信息有哪些?

我在这里用的IE的开发者工具分析,大多数浏览器都有这个功能。

我个人测试qq号的REFERER信息

从这幅图中的REFERER可以看到我个人的qq号。于是我就想把这个图片链接到我个人图片服务器不就行了吗。

http.createServer(function (request, response) {
            fs.readFile('default.png', 'binary', function (err, file) {
            response.writeHead(200, {'Content-Type': 'image/png'});
            response.write(file, 'binary');
            response.end();
        });
}).listen(8080, '127.0.0.1');

这是最简单的读取本地图片并显示的服务器代码。

下面开始增加对refer的判断。我通过http检测工具知道,只有在qq空间的个人中心才能获取到此人的qq号,而在其他位置,如:日志正文,手机qq等页面都是没有此referer的,所以此神奇图片只能在个人中心浏览之后,再加上缓存才能在pc端的其他页面看到。

代码如下:

var http = require('http');
var url = require('url');
var fs = require('fs');

http.createServer(function (request, response) {

   // 如果没有referer就算显示默认图片
    if (!request.headers.referer) {
       return showDefaultPng();
    }

   // referer不是从个人中心过来的也显示默认图片 
    var aQQ = url.parse(request.headers.referer).pathname.match(/\d+/);
    if(aQQ===null) {
       return showDefaultPng();
    }


    // 从腾讯的接口获取qq号对应的个人信息
    http.get('http://base.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins=' + aQQ[0], function (res) {
        var infoBuffer = [];
        res.on('data', function (data) {
            infoBuffer.push(data);
        });
        res.on('end', function () {
            var sInfo = Buffer.concat(infoBuffer);
            var aInfo = sInfo.toString().replace(/"/g, "").match(/\[(.+)\]/);
            if (!aInfo) {
                // 如果不能获取到个人信息,依然显示默认图片
                return showDefaultPng();
            }

            else {
                // 如果能正确获取信息,就需要从qq图片服务器拉取头像
                var a = aInfo[1].split(',')[0];
                var req = http.request({'hostname': url.parse(a).hostname, 'method': 'get', 'port': '80', 'path': url.parse(a).pathname}, function (res) {
                    var data = [];
                    res.on('data', function (chunk) {
                        data.push(chunk);
                    });
                    res.on('end', function () {
                        var buffer = Buffer.concat(data);
                        // 增加缓存,并发送出去
                        response.writeHead(200, {'Content-Type': 'image/png',
                        'Cache-Control': 'public,max-age=31536000'
                        });
                        response.write(buffer, 'binary');
                        response.end();
                    });
                });
                req.end();
            }
        });
    });

    function showDefaultPng() {
        fs.readFile('default.png', 'binary', function (err, file) {
            response.writeHead(200, {'Content-Type': 'image/png'});
            response.write(file, 'binary');
            response.end();
        });
    }


}).listen(8080, '127.0.0.1');

console.log('Server running at http://127.0.0.1:8080/');

http://base.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins=你的qq号 这个链接可以查询到你的qq的基本信息。

ps: 我有两年的JS经验,两年的JAVA经验,搭过express和mongo的个人博客经验,所以也不能说是完全的node新手。

回到顶部