QQ 在線狀態查詢曾是眾多社交應用、客服系統、營銷工具的剛需。雖然騰訊已逐步收緊接口、下線舊版 API,但其核心原理——**通過 HTTP 請求分析響應差異判斷狀態**——對理解 Web 爬蟲、API 逆向、狀態檢測仍有參考價值。本文系統梳理三種主流實現方案及昵稱獲取方法。
騰訊提供 Web 版在線狀態圖標接口:
https://wpa.qq.com/pa?p=1:QQ號:樣式代碼
不同狀態返回不同圖片(亮色=在線,灰色=離線/隱身),導致 **Content-Length** 或 **重定向 Location** 差異。通過分析響應頭或重定向 URL 即可推斷狀態。
<?php
function getQQStatusV1($uin) {
error_reporting(0);
$content = @file_get_contents("https://wpa.qq.com/pa?p=1:{$uin}:4");
if ($content === false) return null; // 網絡錯誤
foreach ($http_response_header as $header) {
if (stripos($header, 'Content-Length') === 0) {
$len = (int)substr($header, 16);
// 經驗閾值:在線圖片通常 > 1000 字節,離線/隱身較小
return $len > 1000;
}
}
return null;
}
// 使用
var_dump(getQQStatusV1(561272831)); // true/false/null
?>
缺點:閾值不穩定,騰訊調整圖片大小即失效;無法區分離線與隱身。
<?php
function getQQStatusV2($uin) {
$request = "GET /pa?p=1:{$uin}:1 HTTP/1.1\r\n";
$request .= "Host: wpa.qq.com\r\n";
$request .= "User-Agent: PHP_QQ_Checker/1.0\r\n";
$request .= "Connection: Close\r\n\r\n";
$socket = @fsockopen('wpa.qq.com', 80, $errno, $errstr, 5);
if (!$socket) return -1; // 連接失敗
fwrite($socket, $request);
$response = '';
while (!feof($socket)) {
$response .= fread($socket, 1024);
}
fclose($socket);
// 解析響應頭尋找 Location
$headers = explode("\r\n", $response);
foreach ($headers as $line) {
if (stripos($line, 'Location:') === 0) {
$location = trim(substr($line, 9));
if (strpos($location, 'online') !== false) return 1; // 在線
if (strpos($location, 'offline') !== false) return 0; // 離線
return -1; // 未知
}
}
return -1;
}
echo getQQStatusV2(561272831); // 1/0/-1
?>
優點:不依賴圖片大小,直接語義判斷;可控超時、User-Agent、Headers。
缺點:Socket 代碼較繁瑣,高併發下文件描述符易耗盡。
<?php
function getQQStatusV3($uin) {
// 樣式 41:在線圖片 Content-Length 固定為 1243(歷史經驗值,可能失效)
$url = 'https://wpa.qq.com/pa?p=2:' . $uin . ':41&r=' . time(); // 防緩存
$headers = @get_headers($url, 1);
if (!$headers) return false;
$len = $headers['Content-Length'] ?? 0;
return $len == 1243; // 經驗值,需定期驗證
}
?>
接口:https://r.qzone.qq.com/cgi-bin/user/cgi_personal_card?uin=QQ號
返回 JSONP 格式,需提取 nickname 字段。
<?php
function getQQNick($qq) {
$url = "https://r.qzone.qq.com/cgi-bin/user/cgi_personal_card?uin={$qq}";
$content = @file_get_contents($url);
if (!$content) return null;
// 正則提取 "nickname":"值"
if (preg_match('/"nickname"\s*:\s*"([^"]+)"/', $content, $m)) {
return $m[1];
}
return null;
}
function getQQName($qq) {
// 可結合本地緩存、好友列表映射等
return getQQNick($qq);
}
echo getQQNick(561272831); // 輸出昵稱或 null
?>
<?php
class QQStatusChecker {
private $cache; // Redis/Memcached 實例
private $ttl = 300; // 5 分鐘緩存
public function __construct($cache) { $this->cache = $cache; }
public function getStatus($uin) {
$key = "qq_status:{$uin}";
if ($this->cache && ($cached = $this->cache->get($key)) !== false) {
return $cached;
}
$status = $this->fetchStatus($uin); // 使用方案二
if ($this->cache && $status !== -1) {
$this->cache->set($key, $status, $this->ttl);
}
return $status;
}
private function fetchStatus($uin) {
// 使用 Guzzle 異步並發、重試、超時控制
// 此處省略,參考方案二邏輯
return 1; // 模擬
}
}
?>
QQ 在線狀態查詢本質是**非官方接口逆向**,方案從簡單的 file_get_contents 到健壯的 Socket/Guzzle 異步併發。**生產環境強烈建議遷移至官方開放平台授權體系**,若必須使用非官方接口,務必做好緩存、限流、降級、監控、合規審查,並預案接口失效時的業務降級方案。