QQ空间的“神奇”图片
昨天女友说遇到了一个奇怪的问题,就是在别人的QQ空间的转载上看到了自己的名字,头像,问我是怎么回事。晚饭后,闲来无事,想到那个问题,就让女友打开那个看到自己头像,名字的网页(因为本人几乎不上空间,所以空间这方面近乎白痴)。看到她说的那个地方是一张图片,使用chrome审查元素发现这张图片来源于一个PHP文件,而且这个文件不是QQ空间自带的:
http://qq.sennvwu.com/qzone/do.php
试图获取一下,无功而返。因为PHP的运行都是在服务器端运行的,而用户看到的网页则是PHP的运行结果,可以说跟源文件没有一毛钱关系,这就很难办了!
想了一下,应该是这样一个流程:用户查看这个文章(初始是一张图片,no.png)——用户点击后文章内调用定的PHP文件——PHP文件获取当前页面的QQ号码——然后通过腾讯的开放接口查询用户的名字,头像并使用其他开放接口获取查看文章用户的ISP——将获取的头像,名字,ISP等信息加上一段话生成一张图片——将这张图片返回到用户查看界面——用户看到神奇的图片。
在网上找了一些资料(毕竟对PHP了解的只是皮毛),发现有大神已经全部搞定,还附带了源码,故转载至此!
以下是转载文章内容:
昨晚上偶然看到个比较坑爹的日志,正文有一张图片,在好友动态列表查看的时候可以显示自己(不是发日志的好友,是你自己)的头像和QQ号码、昵称。正文的文字称,这是“本年度最给力神奇魔力日志(转载会看到你最熟悉的身影)”,并且在文章底部附加了一个发广告的QQ号码。
由于这张坑爹图片的存在,文章转发量短短三天内过千。这招可比那些疯狂加群发广告的来的更有创意和杀伤力,转载传播图片(包括日志当中的广告)的人几乎是全网用户(跟所谓病毒营销差不多了)。好奇的话可以看这篇日志最初来源:hXXp://user.qzone.qq.com/732678621/blog/1363502247
一看就知道是检测referer的把戏。早在几年前BBS还在流行的时候,很多人设置的签名图具有天气预报、客户端信息(浏览器、操作系统、IP所在地之类)、随机笑话、倒计时等五花八门的功能。这都得益于服务器端脚本的图像处理功能。而客户端的检测则是基于HTTP请求中的UserAgent和Referer等信息。
但是印象中QQ空间为了防止referer潜在的安全问题和防止图片被防盗链瞎了很大功夫,凡是发表到QQ空间的日志,正文都会把引用到的所有第三方图片资源缓存到腾讯的云端上。所以直接在日志正文中引用的图片,是不会提交REFER到我们的服务器脚本上的。
文中特别称,“请转载后用电脑进入个人中心看”。为什么要特别说明是“个人中心”呢?我刷新了好久的动态,终于看到了图片所说的效果。页面生成的DOM代码为:
onload="QZFL.media.reduceImage(0,400,300,{trueSrc:'http:\/\/qq.sennvwu.com\/qzone\/do.php',callback:function(img,type,ew,eh,o){var _h = Math.floor(o.oh/o.k),_w = Math.floor(o.ow/o.k);if(_w<=ew && _h<=eh){var p=img.parentNode;p.style.width=_w+'px';p.style.height=_h+'px';}}})"
width="400">
原来QQ空间还是会显示源地址的图片的,仅限于在“个人中心”。这时候请求图片附带的HTTP_REFERER的值为
http://user.qzone.qq.com/QQ号/infocenter
号码就是这样提取到的。如果REFERER不满足条件,这个php将在header中发送Location跳转到同一目录下的no.png。
那么后台是如何取到QQ头像、昵称等信息的呢?我Google到了一个腾讯的WebService接口:
http://base.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins=QQ号
不需要任何凭证信息即可获取uins指定的QQ号码的头像、昵称信息,返回的格式为JSON。另外上面的图片还有一个显示地理位置和ISP的功能,这个就比较常见了。我找到了一个比较好用的接口,来自TB:
http://ip.taobao.com/service/getIpInfo.php?ip=127.0.0.1
格式同样也是JSON。
接下来实现这个效果就比较简单了,通过REFERER检测用户的QQ号码,然后在后台下载头像、昵称等信息,用GD函数绘制上图片,返回客户端。
我也折腾了一个‘神奇图片“发到空间,居然捉弄了一群人。下面是php语言的实现代码。为了减少后端的流量,对下载的头像做了缓存处理:
<?php
error_reporting(0);
ob_start();
header('Content-Type: p_w_picpath/png');
define('IMG_NO', "no.png"); #刚开始显示的提示信息
define('IMG_BACKGROUND', "background.png");
define('IMG_WIDTH', 400);
define('IMG_HEIGHT', 128);
define('FONT_NAME', "AdobeHeitiStd-Regular.otf"); #字体文件名
define('CACHE_PATH', rtrim(realpath("./cache"), '/').'/'); #缓存目录
define('CACHE_EXPIRE', 60*60); #缓存时间,单位秒
#(!is_dir(CACHE_PATH) && is_writable(CACHE_PATH)) || die;
/*
$remote: 远程URL
$local: 本地缓存路径
$expire: 过期时间。为-1时,永久不更新缓存
*/
function load_from_cache($remote, $local, $expire = CACHE_EXPIRE, $as_path = false) {
#过滤潜在的危险字符
$local = preg_replace("/[.\/\\\?\*\'\"\|\:\<\>]/", "_", $local);
$cache = CACHE_PATH.$local;
#查找缓存
if(file_exists($cache) && ($expire = -1 || filemtime($cache) - time() < $expire))
return $as_path ? $cache : file_get_contents($cache);
#文件不存在或缓存过期,重新下载
$content = file_get_contents($remote);
file_put_contents($cache, $content);
return $as_path ? $cache : $content;
}
/*
返回客户端信息。
*/
function client_info() {
$url = "http://ip.taobao.com/service/getIpInfo.php?ip=";
$ip = ($_SERVER["HTTP_VIA"] && $_SERVER["HTTP_X_FORWARDED_FOR"] ?
$_SERVER["HTTP_X_FORWARDED_FOR"] : $_SERVER["REMOTE_ADDR"]);
$info = explode('"', load_from_cache($url.$ip, $ip, -1));
$string = $info[7].$info[23].$info[31].$info[47];
return json_decode('"'.$string.'"');
}
$referer = $_SERVER['HTTP_REFERER'];
#$referer = "http://user.qzone.qq.com/123456789/infocenter";
$pattern = "/http:\/\/user.qzone.qq.com\/(\d+)\/infocenter/";
if(preg_match($pattern, $referer, $matches)) {
#获取QQ号码
$uin = $matches[1];
$info = explode('"', load_from_cache(
"http://base.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins=".$uin, $uin));
$avatar = $info[3];
$nickname = iconv("GBK", "UTF-8//IGNORE", $info[5]);
$client = client_info();
#重点来了,生成图片
try{
$im = p_w_picpathcreatefrompng(IMG_BACKGROUND);
#绘制头像
$avatar_file = load_from_cache($avatar, $uin.".jpg", 60*60*24, true);
$im_avatar = p_w_picpathcreatefromjpeg($avatar_file);
p_w_picpathcopymerge($im, $im_avatar, 14, 14, 0, 0, 100, 100, 100);
p_w_picpathdestroy($im_avatar);
#绘制文字
$blue = p_w_picpathcolorallocate($im, 0, 0x99, 0xFF);
$white = p_w_picpathcolorallocate($im, 0xFF, 0xFF, 0xFF);
$texts = array(
array(12, 148, 40, $white, $uin),
array(18, 125, 70, $blue, $nickname),
array(16, 125, 100, $blue, $client)
);
foreach($texts as $key=>$value) {
p_w_picpathttftext($im, $value[0], 0, $value[1], $value[2], $value[3], FONT_NAME,
mb_convert_encoding($value[4], "html-entities", "utf-8")); #解决乱码问题
}
p_w_picpathpng($im);
p_w_picpathdestroy($im);
header("Content-Length: ".ob_get_length());
ob_end_flush();
} catch (Exception $e) {
#die($e->getMessage());
$error = true;
}
} else {
$error = true;
}
if($error){
header('Content-Length: '.filesize(IMG_NO));
echo file_get_contents(IMG_NO);
}
转载于:https://blog.51cto.com/hero2012/1167795
QQ空间的“神奇”图片相关推荐
- Android开发之QQ空间效果(QQ空间下拉图片放大,松手后回弹)
Android开发之QQ空间效果(QQ空间下拉图片放大,松手后回弹) 腾讯QQ空间的下拉图片放大,松手后回弹的效果带来的视觉差异效果让许多移动开发者心动不已,经本人一段时间的研究,终于实现了该视差效果 ...
- python爬取qq空间锁密图片_Python3爬取QQ空间信息(下)
|下载W3Cschool手机App,0基础随时随地学编程>>戳此了解| 导语 内容回顾: Python爬取QQ空间信息(上) 按照(上)中的安排,本期内容为抓取QQ空间的好友信息并做可视化 ...
- 安卓仿QQ空间实现(含图片的动态编辑、发表、点赞、评论)
之前做项目的时候需要用到仿空间动态的功能,在此做一下记录,简单介绍一下listview自定义适配器以及各相关功能实现方法. 一.效果图 这里添加了两条初始动态,其他都是现编现发的.头像这里后面使用了圆 ...
- 图片较多的网站,如淘宝京东、美丽说花瓣、QQ空间、百度图片等都采用哪些技术优化图片展示?
作者:秦墨鱼 链接:https://www.zhihu.com/question/33309032/answer/95570832 来源:知乎 秦墨鱼是我的好基友,今天转他的文章来讲讲前端图片优化 前 ...
- qq空间留言 php,qq空间留言背景图片 qq励志留言板留言大全
1.韩寒:四年恨一个人比四年爱一个人更糟糕.喜欢只是一种惯性,恨却需要不断地推自己的线. 2.每天告诉自己一次,我真的很好. 3.当你能梦想的时候,就不要放弃梦想. 4.带着爱生活,你会让自己快乐!带 ...
- 空间说说html,qq空间说说带图片 唯美心情说说
1.有些事情,只有经历了,才有穿透心扉的体验:曾经的人,只有从心底放下了,心灵才会真正地解脱. 2.爱上一个人的重要标志就是:遇上任何美景都在遗憾,为何你不在身边. 3.人若软弱就是自己最大的敌人:人 ...
- android 分享纯图片到QQ空间实现方式
最新开发新项目的时候,要做分享项目,要求分享有微信,微信朋友圈,QQ,QQ空间,新浪微博这五个,所分享内容包括,分享纯图片,纯文字,图文类型等,要求分享出去的内容不能带有当前app的logo,而无论使 ...
- 仿QQ空间,百思不得姐下拉刷新图片放大
1.概述 实习生进阶到项目部分会带他们做一个百思不得姐项目,那么个人主页就有类似于QQ空间下拉图片放大的效果,趁着现在还闲就实现一下效果: 2.实现 1. 效果分析 ScrollView和ListVi ...
- 分享到qq空间android,Android将纯图片共享到QQ空间的方式
重要要点: 要将纯图片共享到qq空间,共享sdk不支持纯图片共享,但是可以使用将纯图片共享到qq,设置为自动打开qq空间,这会弹出一个框来共享纯图片,非常有可能共享成功,并且图片不容易过大qq控件分享 ...
最新文章
- saxreader读取服务器xml文件,使用SAXReader从xml文件读取元素
- IDE (Integrated Development Environment) 集成开发环境
- CF1155D Beautiful Array 贪心,dp
- 知乎个人精选 | 绝版的专业书到哪里找最快最高效?
- mysql DCL数据控制语言
- mysql datetime不支持小数_如何从python向MYSQL中插入空小数/datetime?
- win10下mount挂载文件 samba cifs
- Build the backend services needed for a WebRTC app
- python123系统基本信息获取_Python运维-获取当前操作系统的各种信息
- 【Java笔记】IO流(2):字符流
- 测试mysql的查询速度很慢_求助,mysql统计实时数据信息的,查询速度很慢?
- 可视化技巧:显示带colorbar的热图(matplotlib)
- 多看系统下载_制冷系统压力检测有多重要?看了你就知道了
- python能运行vb_vb编程 vb还是python强大
- 通过 wordexport插件 js jq 生成word文档 并导出
- 苹果充电器怎么辨别真假_9款热门充电器盘点:苹果、Anker、紫米、小米、锤子,谁更值得买...
- 「建议观看」史上超长,前端css晦涩难懂的点都在这啦
- python开发库安装(pycharm)
- 工具的服务端口已关闭。要使用命令行调用工具,请打开工具 - 设置 - 安全设置,将服务端口开启。
- 研华板卡1742U--瞬时读值 用 instantAiCtrl1 控件