
简介这是一份PHP版QQ空间最近访客查看器的工具源码定位为轻量级网站查询小工具适合PHP初学者、毕业设计及课程设计人群借鉴。它围绕“最近访客查询”功能提供了一套可运行的PHP实现配套txt说明文件详细介绍部署与使用方式便于快速上手。资源包整体非常小巧共2个文件其中1个php文件为核心功能代码另1个txt文件为使用说明压缩包大小仅3KB携带和部署都很方便。目前已有93人学习下载适合用于理解PHP网页请求、数据交互及简单工具开发的完整思路。代码经过基础验证可直接运行学习者可以将其直接用作QQ空间访客查看工具也可以在原有逻辑上修改扩展改造成其他网站查询或管理模板进一步巩固项目开发能力。同时该资源也常被用作课程设计、大作业或工程实训的初期项目样本帮助初学者快速进入网站开发实战。1. 先说结论这份PHP访客查看器本质是一个能跑的「数据接口展示页」模板QQ空间最近访客查看器PHP版拆开压缩包看到的是一整套可以直接部署的查询工具PHP端负责往QQ空间的访客接口发请求、拿JSON、解析数据HTML端负责把访客头像、昵称、访问时间渲染成一个像样的页面。它不是什么黑科技也没有碰任何违规的东西就是利用了QQ空间网页版自己的访客接口前提是你自己账号的cookie和登录态有效。这工具最适合两类人一是拿它当毕业设计选题的学生二是想快速搭一个「查询类工具站」的开发者。你不需要懂太多前端把PHP文件放进去、改几个参数页面就能出数据。但如果你想本地跑起来、再改造成自己的东西有几个点必须先搞清楚——比如cookie怎么来的、g_tk怎么算、接口返回的字段怎么对上。下面直接从拆包开始讲。2. 拆开压缩包项目结构与本地环境搭建2.1 压缩包里到底有什么五个文件各自的职责拿到qqvisitorphp这个压缩包先别急着往服务器上传。先解压把文件列出来看清每个文件是干嘛的。我解压后看到的典型结构是这样qqvisitorphp/ ├── index.php # 入口文件负责组装页面和处理请求 ├── qq_visitor.php # 核心类库封装访客接口请求与解析 ├── config.php # 配置文件填QQ号和cookie的地方 ├── html/ │ ├── index.html # 静态模板展示访客列表 │ └── assets/ │ ├── style.css # 页面样式 │ └── script.js # 前端交互 └── 使用说明.txt # 作者写的部署说明这个结构很典型入口文件负责调度核心类库负责业务逻辑配置文件负责参数HTML目录负责展示。你在index.php里引入qq_visitor.php调用它的方法拿到数据然后输出HTML。如果只看index.php你会发现它逻辑很薄——基本就是「读配置 → 调类库 → 输出页面」三步。这里有个常见的坑使用说明.txt里写的部署步骤往往很简略只告诉你「修改config.php放到服务器访问index.php」。但实际跑的时候光改config是不够的你还要确认PHP开了curl扩展和json扩展。后面踩坑章节会专门讲。2.2 本地跑起来用phpstudy或宝塔三分钟启动本地调试我一般推荐用 phpstudyWindows下最省事。下载安装后选一个PHP版本我建议用 PHP 7.4 或 8.0太老或太新都可能遇到扩展不兼容的问题。你把解压后的整个文件夹丢到phpstudy_pro\WWW目录下然后启动Apache和MySQL其实这个项目用不到MySQL纯文件型但phpstudy默认一起启动没问题。启动后浏览器访问http://localhost/qqvisitorphp/index.php如果你看到了页面框架但没有数据多半是config.php里的cookie没填或者已经过期。这项目不依赖数据库数据全从QQ空间接口实时拉取所以本地跑通的关键就一个让PHP发出的请求看起来像是一个正常用户在浏览器里访问QQ空间。2.3 参数说明访客接口的URL结构与必填参数访客数据的获取本质是向QQ空间的一个接口发HTTP请求。这个接口的域名是h5.qzone.qq.com路径是/proxy/domain/visitor2.cgi/visitor_list_get。在实际代码里核心类库会把参数拼成一个URL再发请求。典型的参数表如下参数名含义示例值uin目标QQ号查谁就填谁10001proxy_uin代理查询的QQ号一般同uin10001g_tk登录态校验值由cookie里的p_skey算出来1941324059qzonetoken空间令牌登录后从页面或cookie里取一串随机字符format返回格式固定写jsonjsoncount每页返回条数建议1010order排序1表示按访问时间倒序1g_tk不是凭空来的它是由cookie里的p_skey经过一个固定算法算出来的。这个算法是腾讯公开的很多开源项目里都有后面章节会贴代码。qzonetoken则是登录空间后在页面源码里能搜到的一个token字段。如果你是自己登录的账号这两个值能在浏览器开发者工具里直接复制出来。提示当你发现接口返回code: -3000时基本就是g_tk跟cookie不匹配或者token过期了。先去浏览器重新登录一次再复制新的值。这算是这个工具最常见的问题没有之一。3. 核心代码拆解PHP怎么拿到访客JSON并解析3.1 请求流程Cookie、Referer与UA三个头缺一不可要让QQ空间的接口把数据吐给你光有URL是不够的。服务端会校验三个东西请求头里的Cookie、Referer和User-Agent。Cookie用来确认你的登录身份Referer必须指向https://user.qzone.qq.com/你的QQ号让服务端觉得你是在空间页面里发起的请求User-Agent则要伪装成一个完整的Chrome浏览器。我见过有人只填了Cookie没设Referer结果接口返回一堆-3000错误码。这三个头信息在PHP里是通过curl_setopt设置的curl_setopt($ch, CURLOPT_COOKIE, $cookie); // 登录态 curl_setopt($ch, CURLOPT_REFERER, $referer); // 来源页面 curl_setopt($ch, CURLOPT_USERAGENT, $userAgent); // 浏览器标识如果你用浏览器的复制Cookie功能注意别漏掉p_skey这一段。p_skey一般是登录后种在Cookie里的长度在几十到一百多字符之间它直接决定g_tk的值对不对。很多人复制Cookie时习惯只复制一段结果漏了p_skey接口就报错。3.2 PHP代码逐段拆读从curl请求到数组解析核心类库qq_visitor.php的逻辑可以拆成三段计算g_tk、发请求、解析JSON。下面我贴出典型实现并逐段说明。先看g_tk的计算函数这是整个工具的地基?php // 计算g_tkp_skey为cookie中取到的值 function getGTK($p_skey) { $hash 5381; $len strlen($p_skey); for ($i 0; $i $len; $i) { // 左移5位相当于乘32再加字符ASCII码 $hash ($hash 5) ord($p_skey[$i]); } // 转成32位有符号整数等价于JS里的 0x7fffffff return $hash 0x7fffffff; }这个算法的charm点在于它和前端JS版的结果必须完全一致。因为g_tk是前端登录后算出来再随请求发出去的PHP这边如果运算顺序或位运算处理不对算出来的值三五天就变一次接口就间歇性失效。我调试时发现$hash初始值必须是5381不能改成别的否则永远签不上。接下来是发送请求并解析的核心函数?php function getVisitors($uin, $gtk, $qzonetoken, $cookie) { $url https://h5.qzone.qq.com/proxy/domain/visitor2.cgi/visitor_list_get; $params [ uin $uin, proxy_uin $uin, g_tk $gtk, qzonetoken $qzonetoken, format json, count 10, order 1 ]; // 把参数拼接到URL后面 $url . ? . http_build_query($params); $ch curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 本地调试跳过SSL证书验证 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_COOKIE, $cookie); curl_setopt($ch, CURLOPT_REFERER, https://user.qzone.qq.com/{$uin}); curl_setopt($ch, CURLOPT_USERAGENT, Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36); $response curl_exec($ch); curl_close($ch); // 接口返回的是JSON字符串转成数组 $data json_decode($response, true); return $data; }参数说明http_build_query会自动做URL编码比手拼字符串安全CURLOPT_TIMEOUT设15秒是因为访客接口偶尔响应慢不设超时的话PHP进程会一直挂在那SSL_VERIFYPEER和SSL_VERIFYHOST在本地调试时设false省事部署到公网建议改为true并配上证书路径否则容易被安全扫描器标记。拿到返回值后我们真正关心的是data.visitors数组。这个接口返回的结构大致是Array ( [code] 0 [message] ok [data] Array ( [visitors] Array ( [0] Array ( [uin] 123456789 [nickname] 某某 [avatar] https://q1.qlogo.cn/... [visitTime] 1716163200 ) ) [total] 86 ) )注意visitTime是Unix时间戳展示到页面上时要转成日期格式。有些改版把昵称字段写成nick而不是nickname解析的时候建议用isset判断一下别直接取否则PHP会报未定义索引的警告。3.3 数据校验返回为空时先看code再查请求很多人改完参数刷新页面看到的是空列表于是怀疑接口被封了。实际上大部分情况是请求参数没拼对。我自己的调试顺序是先var_dump($data)打印整个返回数组看code字段。code0表示请求成功这时候问题在解析层——比如字段名不匹配。code-3000则说明登录态失效需要重新抓cookie。code-100往往是参数缺失检查g_tk是否为空。这里有一个容易翻车的细节如果你在服务器上调试服务器的IP可能触发QQ空间的异地登录校验。前台表现为接口返回正常但data.visitors为空数组。我遇到过一次后来在config.php里把请求超时调大到30秒问题消失——大概率是服务端延迟导致旧接口提前返回空数据。这个经验不一定适用于所有账号但值得先试。4. 把数据变成页面HTML模板与前端渲染4.1 HTML模板的数据绑定方式PHP直接嵌入还是JS异步压缩包里自带的html/index.html是一份静态模板但真正输出页面时index.php会把PHP解析好的访客数组循环渲染成HTML片段。最早这个模板用的是纯PHP嵌入方式也就是在HTML里写?php foreach ($visitors as $v): ?的写法。好处是简单、不需要跨域坏处是页面和逻辑耦合改样式得在PHP文件里改。如果你要改造成前后端分离常见做法是让PHP只输出JSON前端用fetch异步拉取。比如访问api.php?uin123456时返回JSONscript.js里再渲染卡片。这样做的好处是同一个接口可以给多个页面复用做毕业设计时也更好跟老师讲「前后端数据交互」。我拿到这套模板后更推荐改成异步方案。原因很现实访客接口的响应时延不稳定如果PHP端同步渲染用户打开页面可能要等两秒才看到完整内容改成异步后可以先渲染页面框架数据到了再填充列表体感快很多。4.2 头像加载与时间格式化的两个小坑访客头像字段返回的是QQ头像的URL域名叫q1.qlogo.cn。这个域名在浏览器里直接访问没问题但如果你把页面部署到自己的服务器且设置了严格防盗链头像可能一张都出不来。解决方案是在img标签里加referrerpolicyno-referrer属性或者干脆在PHP端把头像URL换成https://q1.qlogo.cn/g?bqqnk对方QQ号s140这种规范化格式。时间格式化我一般这样处理?php // visitTime是Unix时间戳转成刚刚 / x分钟前 / yyyy-MM-dd HH:mm格式 function formatVisitTime($timestamp) { $diff time() - $timestamp; if ($diff 60) return 刚刚; if ($diff 3600) return floor($diff / 60) . 分钟前; if ($diff 86400) return floor($diff / 3600) . 小时前; return date(Y-m-d H:i, $timestamp); }这个函数的边界就是$timestamp有可能是空的比如旧数据里没存访问时间。调用前加一个empty($timestamp)判断否则date()会告警。4.3 分页与下拉加载count参数和翻页机制访客接口的单次返回条数由count参数控制实测这个接口单次最多返回20条设大了也不会多给。所以要看全部访客就必须做翻页。目前接口没有直接给「页码」参数而是用last_visit_time来做游标第一页请求不带这个参数拿到数据后记住最后一条的visitTime下一页把它作为last_visit_time传进去接口就会返回更早的访客。前端下拉加载的逻辑我封装成这样一个函数// 加载下一页访客数据 function loadMore() { fetch(/api.php?uin qqNumber last_visit_time lastVisitTime) .then(res res.json()) .then(data { if (data.data.visitors.length 0) { document.getElementById(no-more).style.display block; return; } // 追加渲染... lastVisitTime data.data.visitors[data.data.visitors.length - 1].visitTime; }); }注意最后一条lastVisitTime一定要往旧时间方向移动否则接口会一直返回同样的数据表现为列表无限重复。我在第一次写时就翻过车原因就是把时间传反了让接口以为要看最新的数据。5. 避坑实录访客查看器最容易翻车的五个问题5.1 接口返回code: -3000页面一只访客都没有现象填写好config.php后访问index.php页面框架正常但列表区空白抓包看到接口返回{code:-3000,message:...}。原因这是登录态失效或g_tk计算错误。-3000在QQ空间的接口体系里就是「请重新登录」的意思。Cookie过期、p_skey被顶掉、qzonetoken没填对都会触发这个错误。解决打开浏览器重新登录QQ空间在开发者工具里复制最新的Cookie和qzonetoken替换到config.php。同时用前面贴的getGTK函数重新算一遍g_tk。我建议写一个小脚本专门输出g_tk方便随时核对。5.2 有时候能出数据有时候空列表现象同一个配置早上访问有数据下午刷新就空了但接口返回的code仍然是0。原因大概率是触发了QQ空间的频率限制或风控。访客接口对短时间内的请求次数很敏感如果页面每次刷新都实时拉取很容易被临时限制。解决加一层缓存。把访客数据缓存到本地文件或Redis比如设置5分钟有效期。5分钟内的请求直接从缓存读不重复打接口。缓存有效期不宜太长否则访客数据就不「最近」了。5.3 部署到Linux服务器后页面空白现象本地phpstudy一切正常传到服务器上后访问index.php页面空白浏览器控制台显示500错误查看日志看到curl相关报错。原因大概率是服务器上的PHP没有安装或启用curl扩展。Windows版的phpstudy默认带curl但Linux上很多精简安装没有。解决执行下面命令安装扩展然后重启PHP服务。sudo apt install php-curl sudo systemctl restart php7.4-fpm如果是宝塔面板直接在「软件商店」里找到PHP点「安装扩展」勾选curl保存后自动重载。装完再刷新页面基本就能跑通。5.4 访客头像全部显示为默认图或裂图现象昵称和时间都正常但头像全部显示成QQ默认头像或者干脆不显示。原因头像URL被防盗链拦截。QQ头像的CDN会校验Referer如果你的页面域名不是QQ自家的图片请求会被拒绝。解决给所有头像img标签加referrerpolicyno-referrer属性。如果还不行就在PHP端把头像URL里的域名替换为q1.qlogo.cn的标准格式这个域名对Referer的校验最宽松。5.5 本地访问正常手机浏览器打开布局全乱现象电脑上页面很整齐手机上访问排版错乱头像一张张竖着排间距也怪。原因模板里的CSS用的是固定宽度没有加响应式布局。手机浏览器屏幕窄固定宽度直接被截断或缩放。解决在style.css里补一段媒体查询让列表在窄屏下变为单列、头像缩小。常见做法是给列表容器加max-width: 100%再用media (max-width: 600px)调整卡片内边距和头像尺寸。改完记得清一下浏览器缓存再测。6. 拿去做毕业设计或工具站上线前的三个加分改动做到这步你的访客查看器已经能跑起来了。但如果是为了毕业设计答辩或者日后的工具站维护我再推荐三个改动方向。第一把访客查询封装成独立API。改一个api.php接收uin参数返回JSON前端用fetch拉取。这样答辩时你就能清晰说出「前端展示层与后端数据层分离」的架构设计。同时把config.php里的cookie配置改成从环境变量读取避免把敏感信息直接写在文件里。第二给数据加缓存。用文件缓存就够访客数据存到cache/目录下以QQ号日期做文件名有效期5分钟。这能显著降低接口被限流的概率也让你在演示时弱网环境下页面依然秒开。第三做一个「历史访客记录」页面。把每次拉取到的访客数据按时间戳存下来用简单表格展示。虽然原始模板没这个功能但加个history.php并不复杂而且特别契合「最近访客查看器」这个主题——访客来了、走了、哪天来的全都有迹可循。从那以后我每次部署类似的项目都会强制走一遍检查清单curl扩展是否启用、cookie是否最新、缓存是否开启、防盗链是否处理。这套流程虽然简单但帮我省掉了无数次「明明代码没动却突然不能访问」的血泪排查。希望这套拆解和踩坑记录能帮到你尤其是第一次接触QQ空间接口的人按着这篇的顺序走比对着原文摸索要省力得多。本文还有配套的精品资源点击获取