.
684 |
685 |
--------------------------------------------------------------------------------
/QLiker.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import re
4 | import random
5 | import json
6 | import os
7 | import sys
8 | import datetime
9 | import time
10 | import threading
11 | import logging
12 | import execjs
13 | import urllib
14 | from HttpClient import HttpClient
15 |
16 | reload(sys)
17 | sys.setdefaultencoding("utf-8")
18 |
19 | # CONFIGURATION FIELD
20 | checkFrequency = 180
21 | #check every k seconds
22 | # STOP EDITING HERE
23 | HttpClient_Ist = HttpClient()
24 | UIN = 0
25 | skey = ''
26 | Referer = 'https://user.qzone.qq.com/'
27 | QzoneLoginUrl = 'https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&pt_qr_app=%E6%89%8B%E6%9C%BAQQ%E7%A9%BA%E9%97%B4&pt_qr_link=https%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=https%3A//z.qzone.com/download.html&pt_no_auth=0'
28 |
29 | initTime = time.time()
30 |
31 |
32 | logging.basicConfig(filename='log.log', level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S')
33 |
34 | def getAbstime():
35 | return int(time.time())
36 |
37 | def date_to_millis(d):
38 | return int(time.mktime(d.timetuple())) * 1000
39 |
40 | def getReValue(html, rex, er, ex):
41 | v = re.search(rex, html)
42 |
43 | if v is None:
44 | logging.error(er)
45 |
46 | if ex:
47 | raise Exception, er
48 | return ''
49 |
50 | return v.group(1)
51 |
52 | def getQRtoken(qrsig):
53 | e = 0
54 | for i in qrsig:
55 | e += (e << 5) + ord(i)
56 | return 2147483647 & e;
57 |
58 | # -----------------
59 | # 登陆
60 | # -----------------
61 | class Login(HttpClient):
62 | MaxTryTime = 5
63 |
64 | def __init__(self, vpath, qq=0):
65 | global UIN, Referer, skey
66 | self.VPath = vpath # QRCode保存路径
67 | AdminQQ = int(qq)
68 | logging.critical("正在获取登陆页面")
69 | self.setCookie('_qz_referrer','qzone.qq.com','qq.com')
70 | self.Get(QzoneLoginUrl,'https://qzone.qq.com/')
71 | StarTime = date_to_millis(datetime.datetime.utcnow())
72 | T = 0
73 | while True:
74 | T = T + 1
75 |
76 | self.Download('https://ssl.ptlogin2.qq.com/ptqrshow?appid=549000912&e=2&l=M&s=3&d=72&v=4&t=0.{0}6252926{1}2285{2}86&daid=5'.format(random.randint(0,9),random.randint(0,9),random.randint(0,9)), self.VPath)
77 | LoginSig = self.getCookie('pt_login_sig')
78 | QRSig = self.getCookie('qrsig')
79 | logging.info('[{0}] Get QRCode Picture Success.'.format(T))
80 | while True:
81 | html = self.Get('https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&ptqrtoken={0}&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-{1}&js_ver=10220&js_type=1&login_sig={2}&pt_uistyle=40&aid=549000912&daid=5&'.format(getQRtoken(QRSig),date_to_millis(datetime.datetime.utcnow()) - StarTime, LoginSig), QzoneLoginUrl)
82 | # logging.info(html)
83 | ret = html.split("'")
84 | if ret[1] == '65' or ret[1] == '0': # 65: QRCode 失效, 0: 验证成功, 66: 未失效, 67: 验证中
85 | break
86 | time.sleep(2)
87 | if ret[1] == '0' or T > self.MaxTryTime:
88 | break
89 |
90 | if ret[1] != '0':
91 | raise ValueError, "RetCode = "+ret[1]
92 | return
93 | logging.critical("二维码已扫描,正在登陆")
94 |
95 | # 删除QRCode文件
96 | if os.path.exists(self.VPath):
97 | os.remove(self.VPath)
98 |
99 | # 记录登陆账号的昵称
100 | tmpUserName = ret[11]
101 |
102 | self.Get(ret[5])
103 | UIN = getReValue(ret[5], r'uin=([0-9]+?)&', 'Fail to get QQ number', 1)
104 | Referer = Referer+str(UIN)
105 | skey = self.getCookie('p_skey')
106 | logging.critical("Successfully Login, Username: "+str(tmpUserName))
107 |
108 | # -----------------
109 | # 计算g_tk
110 | # -----------------
111 | def utf8_unicode(c):
112 | if len(c)==1:
113 | return ord(c)
114 | elif len(c)==2:
115 | n = (ord(c[0]) & 0x3f) << 6
116 | n += ord(c[1]) & 0x3f
117 | return n
118 | elif len(c)==3:
119 | n = (ord(c[0]) & 0x1f) << 12
120 | n += (ord(c[1]) & 0x3f) << 6
121 | n += ord(c[2]) & 0x3f
122 | return n
123 | else:
124 | n = (ord(c[0]) & 0x0f) << 18
125 | n += (ord(c[1]) & 0x3f) << 12
126 | n += (ord(c[2]) & 0x3f) << 6
127 | n += ord(c[3]) & 0x3f
128 | return n
129 |
130 | def getGTK(skey):
131 | hash = 5381
132 | for i in range(0,len(skey)):
133 | hash += (hash << 5) + utf8_unicode(skey[i])
134 | return hash & 0x7fffffff
135 | # -----------------
136 | # LIKE
137 | # -----------------
138 | def like(unikey,curkey,dataid,time,qztoken):
139 | reqURL = 'https://h5.qzone.qq.com/proxy/domain/w.qzone.qq.com/cgi-bin/likes/internal_dolike_app?g_tk={0}&qzonetoken={1}'.format(str(getGTK(skey)),str(qztoken))
140 | data = (
141 | ('qzreferrer', Referer),
142 | ('opuin', UIN),
143 | ('unikey', str(unikey)),
144 | ('curkey', str(curkey)),
145 | ('from', '1'),
146 | ('appid', '311'),
147 | ('typeid', '0'),
148 | ('abstime', str(time)),
149 | ('fid', str(dataid)),
150 | ('active', '0'),
151 | ('fupdate', '1')
152 | )
153 | rsp = HttpClient_Ist.Post(reqURL, data, Referer)
154 | getReValue(rsp, r'"code":(0)', 'Fail to like unikey='+str(unikey)+';curkey='+str(curkey)+';fid='+str(dataid), 0)
155 |
156 | # -----------------
157 | # 主函数
158 | # -----------------
159 | def MsgHandler():
160 | html=HttpClient_Ist.Get(Referer+'/infocenter?via=toolbar',Referer)
161 | fkey=re.findall(r'', split_string[i+1])
172 | if btn_string is None:
173 | continue
174 | abstime = re.search(r'data-abstime="(\d*?)"',split_string[i+1])
175 | if abstime is None:
176 | continue
177 | like(btn_string.group(1),btn_string.group(2),fkey[i],abstime.group(1),qztoken)
178 | logging.info('已点赞'+btn_string.group(2))
179 | except Exception, e:
180 | logging.error(str(e))
181 |
182 | # -----------------
183 | # 主程序
184 | # -----------------
185 |
186 | if __name__ == "__main__":
187 | vpath = './v.png'
188 | qq = 0
189 | if len(sys.argv) > 1:
190 | vpath = sys.argv[1]
191 | if len(sys.argv) > 2:
192 | qq = sys.argv[2]
193 |
194 | try:
195 | qqLogin = Login(vpath, qq)
196 | except Exception, e:
197 | logging.critical(str(e))
198 | os._exit(1)
199 | errtime=0
200 | while True:
201 | try:
202 | if errtime > 5:
203 | break
204 | MsgHandler()
205 | time.sleep(checkFrequency)
206 | errtime = 0
207 | except Exception, e:
208 | logging.error(str(e))
209 | errtime = errtime + 1
210 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | QQ空间点赞机
2 | =========
3 | [](https://travis-ci.org/zeruniverse/QzoneLiker)
4 | [](https://landscape.io/github/zeruniverse/QzoneLiker/master)
5 | [](https://www.codacy.com/app/zzy8200/QzoneLiker)
6 | 
7 | 
8 | 
9 |
10 | QQ空间点赞机,成为秒赞小王子~!
11 | 注意:由于TX经常更改协议,如果RELEASE中最新版无法使用,请尝试MASTER分支。
12 |
13 | ## RELEASE
14 | Python Version: [DOWNLOAD](https://github.com/zeruniverse/QzoneLiker/releases/latest)
15 | ~~Windows Version (32位exe): [https://github.com/zeruniverse/QzoneLiker/releases/tag/w1.1](https://github.com/zeruniverse/QzoneLiker/releases/tag/w1.1)~~
16 | Windows版已停止更新,请Windows用户使用技术门槛更低的网页版[QBotWrap](https://github.com/zeruniverse/QBotWebWrap)
17 |
18 | ## 如何使用
19 | + 安装`PyExecJS`: `pip2 install PyExecJS`
20 | + 下载后使用Python2运行QLiker.py
21 | + ```nohup python2 QLiker.py >qliker.log&```
22 | + ```ls```, 直到出现v.png
23 | + 下载v.png,使用手机QQ扫描登陆
24 | + 如需更改默认刷新频率,请更改代码第19行(默认180秒,刷新太快网页空间会被封,直接显示为403)
25 |
26 | ## 功能
27 | + 自动点赞,每N秒刷新一次。后台挂机运行
28 |
29 | ## WEB托管
30 | [QBotWrap](https://github.com/zeruniverse/QBotWebWrap): 摆脱命令行,直接用浏览器操作挂机!
31 |
32 | ## 贡献代码
33 | 欢迎提交Pull Request! (如果您提交Pull Request, 则视为您同意将您编写的部分代码以GNU GPL v3.0协议随同本项目发布)
34 |
--------------------------------------------------------------------------------