首先要处理的是gtk算法:从上次分析以来代码并没有变
登录QQ空间后搜索gtk字符串,在三个js中出现了
operation.50303.js
gdtlib.20160810.js
index.js
第一个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);
}
);
}
;
}
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);
}
;
/**
* @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;
}
}
QZONE.FP.getACSRFToken(url)
url通过前面传的参数拼接
找到这个js
interface_mini.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;
};
qzfl_v8_2.1.60.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;
};
这次获取的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
运行之前先安装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的引号里面,然后运行即可
1.python3把int long合并为int型,左移的代码又不能去掉,所以把int和long类型判断改成数值范围判断,没了long,数值后面的L也要去掉
2.print只能是函数形式了,这里全改成函数形式