python展示全部好友_Python3.6獲取QQ空間全部好友列表

首先要處理的是gtk算法:從上次分析以來代碼並沒有變

登錄QQ空間后搜索gtk字符串,在三個js中出現了

/* |xGv00|e5808eb94a2bdffe3aae60cd22c5efe2 */

define("app/v8/controls/mood_poster/utils/misc/1.0", ["app/v8/utils/tmpl/1.0"], function(require, exports, module) {

var tmpl = require('app/v8/utils/tmpl/1.0');

var misc = {};

var getUploadUrl = function(callback) {

misc.getRoute(function(routeDomainMap) {

var gtk = 5381;

var url = ['http://', routeDomainMap['u'].replace('photo.qq.com', 'photo.qzone.qq.com'), '/cgi-bin/upload/cgi_upload_image'].join('');

try {

gtk = QZONE.FP.getACSRFToken(url);

} catch (err) {}

callback(url + '?g_tk=' + gtk);

}

);

}

;

}

第二個js

HMod.genGTk = function() {

var skey = comm.cookie.get("skey") || comm.cookie.get("rv2");

return comm.genHash(skey);

}

;

NMod.xhrgetter = function(url, callback, ecb, opts) {

var pid, gtk, domain = document.domain, usecors, valuestaturl = 'http://i.gdt.qq.com/view.fcg?xhr2';

opts = opts || {};

gtk = NMod._ishostSupportxhr() ? helper.genGTk() : '';

if (supportlv2 && NMod._ishostSupportxhr()) {

gtk && (url += '&g_tk=' + gtk);

comm.xhr(url, function(obj) {

NMod._decodexhrjson(obj.resp, callback, ecb);

}

, function(obj) {

ecb(obj);

if (obj && obj.exception && obj.status == 598) {

helper.sendErrMsg(obj.exception, location.href + '&gxhr', '', {

extra: "get xhr transport error",

rate: 100

});

}

}

, opts);

helper.valueStat(valuestaturl, 1, 11, 1, 500);

return;

}

opts.forcescript = true;

NMod._normalgetter(url, callback, ecb, opts);

helper.valueStat(valuestaturl, 1, 12, 1, 500);

}

;

第三個js

/**

* @fileOverview 首頁,入口文件

* @author Viktor Li

*/

define.pack("./index", ["lib/jquery", "mall.v8/lib/mall", "./event", "./tmpl", "./asyncRender"], function(require, exports, module) {

var $ = require('lib/jquery')

,

M = require('mall.v8/lib/mall');

var evt = require('./event')

,

TMPL = require('./tmpl')

,

asyncRender = require('./asyncRender');

//發起一個img請求ping后台

function Ping(url, arg) {

arg = arg || {};

if (!('g_tk' in arg)) {

//補上gtk

arg.g_tk = M.user.getToken();

}

var sender = new Image

,

params = $.param(arg);

url = url + (url.indexOf('?') === -1 ? '?' : '&') + params;

sender.src = url;

}

}

看第一個js就夠了

這個js從定義的名稱來看是獲取上傳路徑的

關鍵還是這一句

QZONE.FP.getACSRFToken(url)url通過前面傳的參數拼接

找函數定義相對准確的做法是用開發者工具watch查看QZONE.FP這個對象,然后找到getACSRFToken(url),右鍵 show function definition 查看函數定義(

右鍵的位置很重要)

找到這個js

QZONE.FrontPage.getACSRFToken = function(url) {

url = QZFL.util.URI(url);

var skey;

if (url) {

if (url.host && url.host.indexOf("qzone.qq.com") > 0) {

skey = QZFL.cookie.get("p_skey");

} else {

if (url.host && url.host.indexOf("qq.com") > 0) {

skey = QZFL.cookie.get("skey");

}

}

}

if (!skey) {

try {

skey = parent.QZFL.cookie.get("p_skey") || "";

} catch (err) {

skey = QZFL.cookie.get("p_skey") || "";

}

}

if (!skey) {

skey = QZFL.cookie.get("skey") || QZFL.cookie.get("rv2");

}

var hash = 5381;

for (var i = 0, len = skey.length;i < len;++i) {

hash += (hash << 5) + skey.charAt(i).charCodeAt();

}

return hash & 2147483647;

};

可能是為了方便調用,定義也出現在下面這個js里

QZFL.pluginsDefine.getACSRFToken = function(url) {

url = QZFL.util.URI(url);

var skey;

if (url) {

if (url.host && url.host.indexOf("qzone.qq.com") > 0) {

try {

skey = parent.QZFL.cookie.get("p_skey");

} catch (err) {

skey = QZFL.cookie.get("p_skey");

}

} else {

if (url.host && url.host.indexOf("qq.com") > 0) {

skey = QZFL.cookie.get("skey");

}

}

}

if (!skey) {

skey = QZFL.cookie.get("p_skey") || (QZFL.cookie.get("skey") || (QZFL.cookie.get("rv2") || ""));

}

return arguments.callee._DJB(skey);

};

QZFL.pluginsDefine.getACSRFToken._DJB = function(str) {

var hash = 5381;

for (var i = 0, len = str.length;i < len;++i) {

hash += (hash << 5) + str.charCodeAt(i);

}

return hash & 2147483647;

};

//兩個定義大體上時一樣的

先看具體情況生成要計算的skey

1.如果url中含有指定主機名,獲取cookie中的p_skey或skey作為要計算的skey

2.如果通過url的方式沒有獲取到,則獲取cookie中的p_skey作為要計算的skey

3.如果通過以上兩種方式還沒有獲取到,則獲取cookie中的p_skey||rv2作為要計算的skey

QZFL.pluginsDefine對象中的定義將23進行了合並

如果URL方式沒獲取到,則獲取cookie中的p_skey||skey||rv2||""作為要計算的skey

從命名上和邏輯上推測p_skey和skey的關系應該是:當前域的p_skey=當前域的父域的skey值

后面的計算方式沒變,這個計算方式很早就有了

這次獲取的js和15年的沒什么區別,這次就把獲取方法和具體算法說詳細一點

Python3版本的gtk算法代碼如下,主機名判斷懶得搞了,直接用QZFL.pluginsDefine的第二步,反正能用

def LongToInt(value): # 由於int+int超出范圍后自動轉為long型,通過這個轉回來

if value > 0x7fffffff or value < 0x80000000:

return int(value & 0x7fffffff)

else:

return int(value)

def LeftShiftInt(number, step): # 由於左移可能自動轉為long型,通過這個轉回來

if (number << step) > 0x7fffffff or (number << step) < 0x80000000:

return int((number << step) - 0x200000000)

else:

return int(number << step)

def getNewGTK(p_skey, skey, rv2):

b = p_skey or skey or rv2

a = 5381

for i in range(0, len(b)):

a = a + LeftShiftInt(a, 5) + ord(b[i])

a = LongToInt(a)

return a & 0x7fffffff

Python3的完整版獲取QQ空間好友列表代碼

運行之前先安裝httplib2

pip install httplib2

# -*- coding: UTF-8 -*-

import httplib2

import json

import re

def LongToInt(value): # 由於int+int超出范圍后自動轉為long型,通過這個轉回來

if value > 0x7fffffff or value < 0x80000000:

return int(value & 0x7fffffff)

else:

return int(value)

def LeftShiftInt(number, step): # 由於左移可能自動轉為long型,通過這個轉回來

if (number << step) > 0x7fffffff or (number << step) < 0x80000000:

return int((number << step) - 0x200000000)

else:

return int(number << step)

def getNewGTK(p_skey, skey, rv2):

b = p_skey or skey or rv2

a = 5381

for i in range(0, len(b)):

a = a + LeftShiftInt(a, 5) + ord(b[i])

a = LongToInt(a)

return a & 0x7fffffff

h = httplib2.Http()

url = 'http://m.qzone.com/friend/mfriend_list?g_tk=[g_tk]&res_uin=[QQ號碼]&res_type=normal&format=json&count_per_page=10&page_index=0&page_type=0&mayknowuin=&qqmailstat='

myqq=''

cookieStr = ''

headers = {'Cookie': cookieStr}

if re.search(r'p_skey=(?P[^;]*)', cookieStr):

p_skey = re.search(r'p_skey=(?P[^;]*)', cookieStr).group('p_skey')

else:

p_skey = None

if re.search(r'skey=(?P[^;]*)', cookieStr):

skey = re.search(r'skey=(?P[^;]*)', cookieStr).group('skey')

else:

skey = None

if re.search(r'rv2=(?P[^;]*)', cookieStr):

rv2 = re.search(r'rv2=(?P[^;]*)', cookieStr).group('rv2')

else:

rv2 = None

print('gtk='+str(getNewGTK(p_skey, skey, rv2)))

url = url.replace('[g_tk]', str(getNewGTK(p_skey, skey, rv2)))

url = url.replace('[QQ號碼]', myqq)

print(url)

resp, content = h.request(url, 'GET', headers=headers)

print(resp)

print(content)

output = json.loads(content) # json字符串轉字典

if output['code'] == -3000:

print(output['message'])

else:

items_list = output['data']['list']

qqlist = set()

for item in items_list:

qqlist.add(item['uin'])

# 打印信息並輸出到文件

print('獲取QQ號個數' + str(len(qqlist)))

filename = 'qqlist.txt'

fileobj = open(filename, 'w')

result = [str(qq) + '\n' for qq in sorted(qqlist)]

fileobj.writelines(result)

fileobj.flush()

fileobj.close()

print('寫入完成')

使用方法:復制cookie字符串和QQ號粘貼到cookieStr和myqq的引號里面,然后運行即可

Python2版本的代碼相比,處理了以下幾個小問題

1.python3把int long合並為int型,左移的代碼又不能去掉,所以把int和long類型判斷改成數值范圍判斷,沒了long,數值后面的L也要去掉

2.print只能是函數形式了,這里全改成函數形式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值