获取QQ好友列表

  获取QQ好友列表的方法确实不多,3GQQ是一种办法,不过最简单的就是QQ邮箱获取了,这里有用了这种方式。QQ邮箱如果使用模拟登陆的话,又实在太麻烦,采取折中的方式,首先登陆,然后使用COOKIE模拟。
QQ邮箱主界面
  QQ邮箱可以发现又两个主要信息,其一为地址栏的地址,包含SID等。其二就是为COOKIE信息,可以在网络状况查询中很直观的获取。接下来使用PHP类获取。

<?php

/**
 * QQ 好友列表获取类
 * 使用方式:
 *
 * $qg = new Get_QQ_List();
 * $ql->setUrl("https://mail.qq.com/c****");
 * $ql->setCookie("tui_loginuin=2*************");
 * $ql->dump();
 *
 * 使用脚本方式运行,php get_qq_list.php > E:\qq.html
 * 执行HTML页面后,JS解析出一个表格,复制到EXECL中后可进行更复杂的操作
 *
 * Class Get_QQ_List
 */

class Get_QQ_List
{
    /**
     * @var string 用户SID
     */

    private $sid;
    /**
     * @var string 引用页
     */

    private $referer;

    /**
     * @var resource CURL句柄
     */

    private $ch;

    /**
     * @var string COOKIE 字符串
     */

    private $cookie;

    function __construct()
    {
        $this->ch = curl_init();
        //禁止验证SSL信息
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    }

    /**
     * 设置访问网址,和来路域名,即访问QQ邮箱跳转后的页面
     * @param $url string
     * @throws Exception
     */

    public function setUrl($url)
    {
        $this->referer = $url;
        preg_match_all("/sid=(.*)&/", $url, $matches);
        if(isset($matches[1][0]))
        {
            $this->sid = $matches[1][0];
        }else
        {
            throw new Exception("无法解析SID");
        }
    }

    /**
     * 设置从浏览器获取来的COOKIE信息
     * @param $cookie string
     */

    public function setCookie($cookie)
    {
        $this->cookie = $cookie;
    }

    /**
     * 设置相应的头信息
     */

    private function setHeader()
    {
        curl_setopt($this->ch, CURLOPT_URL, "https://set2.mail.qq.com/cgi-bin/laddr_list?sid=" . $this->sid . "&operate=view&t=contact&view=normal&loc=frame_html,,,23");
        curl_setopt($this->ch, CURLOPT_COOKIE, $this->cookie);
        curl_setopt($this->ch, CURLOPT_HEADER, 0);
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($this->ch, CURLOPT_REFERER, $this->referer);
        curl_setopt($this->ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36");
    }

    /**
     * 开始输出信息
     * @throws Exception
     */

    public function dump()
    {
        if(empty($this->cookie) || empty($this->referer) || empty($this->sid))
        {
            throw new Exception("信息设置不全");
        }
        $this->setHeader();
        $data = curl_exec($this->ch);
        if($data === FALSE)
        {
            $this->error();
        }
        $list = $this->parse_group($data);
        $rt = "";
        foreach($list as $v)
        {
            $rt .= $this->get_page($v);
        }
        curl_close($this->ch);
        echo $this->parse_file($rt);
    }

    /**
     * 获取单独的列表页面
     * @param $url
     * @return string
     */

    private function get_page($url)
    {
        curl_setopt($this->ch, CURLOPT_URL, "https://set2.mail.qq.com" . $url);
        $data = curl_exec($this->ch);
        if($data === FALSE)
        {
            $this->error();
        }
        return $data . "\n\n\n\n";
    }

    /**
     * 解析页面文件
     * @param $c
     * @return string
     */

    private function parse_file($c)
    {
        //$c = file_get_contents($c);
        $c = explode("\n", $c);
        $ss = "var goListData = ";
        $obj = [];
        foreach($c as &$v)
        {
            if(strpos($v, $ss) === 0)
            {
                $obj[] = substr($v, strlen($ss), -1);
            }
            $v = NULL;
        }
        $data = 'var data = [' . implode(",\n", $obj) . '];';
        $data = mb_convert_encoding($data, 'UTF-8', 'GBK'); //转换内容编码为UTF-8
        $info = <<<HTMLDATA
<html>
<head>
  <title>QQ联系人</title>
  <meta charset="utf-8">
</head>
<body>
<script>
{$data}
document.write("<table><thead><tr><td>名字</td><td>QQ</td><td>昵称</td><td>分组</td></tr></thead>");
for (var obj in data) {
  for (var info in data[obj]) {
    for (var ddd in data[obj][info]) {
      var one = data[obj][info][ddd];
      var nickname = '';
      var qq = one['oEmail'][0]['sVal'].split('@');
      qq = qq[0];
      if (typeof one['oCustom'] != 'undefined' && typeof one['oCustom'][0] != 'undefined' && typeof one['oCustom'][0]['sVal'] != 'undefined') {
        nickname = one['oCustom'][0]['sVal'];
      } else {
        nickname = one['oName'][0]['sVal'];
      }
      document.write("<tr><td>" + one['oName'][0]['sVal'] + "</td><td>" +
              qq + "</td><td>" + nickname + "</td><td>" + one['oGroup'][0]['sName'] + "</td></tr>");
    }
  }
}
document.write("</table>");
</script>
</body>
</html>
HTMLDATA
;
        return $info; //返回一个HTML解析的页面
    }

    /**
     * 分组列表解析
     * @param $data
     * @return array
     */

    private function parse_group($data)
    {
        $i = strpos($data, "navlist_min navlist_qq");
        $j = strpos($data, "panel_info settingtable qqshowbd");
        $data = substr($data, $i, $j - $i);
        preg_match_all('/<li class="fs"><a href="(.*?)"><span ui-type="grouptitle">/', $data, $matches);
        if(isset($matches[1][0]))
        {
            return $matches[1];
        }
        return [];
    }

    /**
     * 错误信息输出
     */

    private function error()
    {
        echo "ERROR:" . curl_error($this->ch);
        exit;
    }
}

  运行过程中必须保持浏览器不关闭,否则会导致COOKIE过期,而无法获取任何信息。导出的列表并没有解析,原始数据为javascript变量,直接使用浏览器去解析可以很方便。因此导出一个HTML文件,然后生成一个表格。利用生成的表格就行了。导出的数据有四项,包含QQ号、QQ备注、QQ昵称、QQ好友分组。

15条评论在“获取QQ好友列表”

回复 恋羽   取消