空间点赞 Python爬虫实战:QQ空间全自动点赞工具

私信小编01即可获取大量Python学习资料
前景提要因为我周围的小伙伴们天天跟我说的最多的一句话就是:空间第一条点赞 。
所以说我还不如直接做一个自动点赞的代码呢 , 免得天天催我点赞 。
目标确定QQ空间秒赞分析介绍登陆获取cookie首先既然是对 QQ空间的一系列操作 , 自然是先解决登陆方面 , 在这篇文章里面我就不过多介绍了 , 因为我上几期之前对QQ空间已经做了一定的介绍了 。直接放出链接就好 。欢迎看博主以前的文章
def search_cookie():qq_number = input('请输入qq号:')if not __import__('os').path.exists('cookie_dict.txt'):get_cookie_json(qq_number)with open('cookie_dict.txt', 'r') as f:cookie=json.load(f)return Truedef get_cookie_json(qq_number):password = __import__('getpass').getpass('请输入密码:')from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionslogin_url = 'https://i.qq.com/'chrome_options =Options()chrome_options.add_argument('--headless')driver = webdriver.Chrome(options=chrome_options)driver.get(login_url)driver.switch_to_frame('login_frame')driver.find_element_by_xpath('//*[@id="switcher_plogin"]').click()time.sleep(1)driver.find_element_by_xpath('//*[@id="u"]').send_keys(qq_number)driver.find_element_by_xpath('//*[@id="p"]').send_keys(password)time.sleep(1)driver.find_element_by_xpath('//*[@id="login_button"]').click()time.sleep(1)cookie_list = driver.get_cookies()cookie_dict = {}for cookie in cookie_list:if 'name' in cookie and 'value' in cookie:cookie_dict[cookie['name']] = cookie['value']with open('cookie_dict.txt', 'w') as f:json.dump(cookie_dict, f)return Truedef get_g_tk():p_skey = self.cookie['p_skey']h = 5381for i in p_skey:h += (h << 5) + ord(i)g_tk = h & 2147483647寻找XML当我们拿到cookie信息和g_tk这个参数之后 , 继续去寻找空间好友动态的XML在何处 。
首先点到XML位置一个个查找 , 发现有一个feeds3_html_more很像 , 点进去发现的确是我们要找的url链接 。



空间点赞 Python爬虫实战:QQ空间全自动点赞工具

文章插图
寻找可变参数这个链接所需要的参数有很多 , 在这里列举出来
uin:scope:view:daylist:uinlist:gid:flag:filter:applist:refresh:aisortEndTime:aisortOffset:getAisort:aisortBeginTime:pagenum:externparam:firstGetGroup:icServerTime:mixnocache:scene:begintime:count:dayspac:sidomain:useutf8:outputhtmlfeed:rd:usertime:windowId:g_tk:qzonetoken:g_tk:这些参数中类似于可变参数的一共有五个 。
qzonetokenwindowIdrdusertimeg_tkqzonetoken 参数在源码中是个可变的“定值” , 因为每次刷新这个参数都会变 , 但是源码中却给出了他的具体值 。直接获取即可 。

空间点赞 Python爬虫实战:QQ空间全自动点赞工具

文章插图
def get_space():your_url = 'https://user.qzone.qq.com/' + str(qq_number)html = requests.get(your_url,headers=headers,cookies=cookie)if html.status_code == 200:qzonetoken = re.findall('window.g_qzonetoken =(.*?);',html.text,re.S)[1].split('"')[1]return TruewindowId 与 rd 虽说每次刷新结果都不同 , 但是经过博主多次实验得出 , 这两个参数对整体并没有什么影响 , 可以直接抄下来 。'rd': '0.9311604844249088','windowId': '0.51158950324406',usertime 参数看似很眼熟 , 是个时间戳参数 , 因为位数不对 , 说明应该是被放大了一千倍 。'usertime': str(round(time.time() * 1000)),g_tk 参数上次教程已给出 。在JavaScript中分析即可获得 。def get_g_tk():p_skey = self.cookie['p_skey']h = 5381for i in p_skey:h += (h << 5) + ord(i)g_tk = h & 2147483647获取第一个空间动态我们拿到XML以及各个参数后 , 即可访问该网页获取其返回值了 。
但是这个返回与其他的有一些不同的是 , 它不仅仅是个json文件 , 我们无法获取后直接转换成字典格式去给我们使用 , 这就很麻烦 。



空间点赞 Python爬虫实战:QQ空间全自动点赞工具

文章插图

我们获取字符串后 , 首先先将前后不一致的都切片扔掉 , 之后经过一系列处理后发现 , 我们很难将这个看似像json格式的字符串转换成字典 。
在这里我继续介绍一个第三方库demjson 。
demjson 可以解決不正常的json格式数据
demjson的使用方法很简单 。
encode将 Python 对象编码成 JSON 字符串decode将已编码的 JSON 字符串解码为 Python 对象
# 例子# -*- coding: utf-8 -*-import demjsonjs_json = "{x:1, y:2, z:3}"py_json1 = "{'x':1, 'y':2, 'z':3}"py_json2 = '{"x":1, "y":2, "z":3}'data = https://www.hedan60.com/baike2/demjson.decode(js_json)print(data)# {'y': 2, 'x': 1, 'z': 3}data = demjson.decode(py_json1)print(data)# {'y': 2, 'x': 1, 'z': 3}data = demjson.decode(py_json2)print(data)# {'y': 2, 'x': 1, 'z': 3}我们使用demjson直接将该字符串转换为耳熟能详的字典格式 , 提取其中的data的data , 即为前八条动态的每个参数 , 但我们这里只要第一个说说的动态信息 。
text = html.text[10:-2].replace(" ", "").replace('n','')json_list = demjson.decode(text)['data']['data']qq_spaces = json_list[0]我们拿到其信息后 , 先提取一些我们比较想知道的东西 , 比如名字、QQ号、发布时间、所获赞数、说说内容、说说地址等等结果 。
在 qq_spaces 参数中我们发现里面有一个很长也很特殊的一个结果是 html 结果 , 这个结果里面很长 , 简单来看是个网页常规代码 , 应该是被JavaScript写入到网页中了 , 既然不是全部代码 , 那么只能用正则提取一下里面的具体我们需要的东西了 。
content = str(qq_spaces['html'])try:zanshu = re.findall('<spanclass="f-like-cnt">(.*?)</span>人觉得很赞</div>',content,re.S)[0]except:return Nonetime_out = str(qq_spaces['feedstime'])print("名字:"+str(qq_spaces['nickname']))print("QQ号:"+str(qq_spaces['opuin']))print("时间:"+time_out)print('赞数:'+zanshu)times = qq_spaces['abstime']his_url = re.findall('data-curkey="(.*?)"',content,re.S)[0]寻找点赞所需的URL【空间点赞 Python爬虫实战:QQ空间全自动点赞工具】在QQ空间随便找个好友点个赞吧 , 这样我们才能接收到请求 。
我们首先清空原来动态产生的抓包 , 直接点个赞发现关于dolike的url只有三个 , 第一个是个POST请求 , 应该是我们所需要的点赞网址 。



空间点赞 Python爬虫实战:QQ空间全自动点赞工具

文章插图
寻找可变参数我们获取到URL后 , 找到里面所需要的参数 。发现一共有十一个参数 , 在这里猜测应该不存在加密参数 。
qzreferrer参数为自己QQ空间的网址 , 表示从哪里来的链接地址 。opuin参数为自己的QQ号 , 可以直接在代码提取 。unikey参数与curkey参数为被点赞方的链接 , 即说说链接 , 刚才已获取 。abstime参数为被点赞方说说的发布时间的时间戳 。fid参数为被点赞方的链接后缀 。既然参数没什么问题那就直接写代码吧 。
def get_zan(times,his_url):data = https://www.hedan60.com/baike2/{'g_tk': g_tk,'qzonetoken': qzonetoken}post_data = {'qzreferrer': 'https://user.qzone.qq.com/'+str(qq_number),'opuin': str(qq_number),'unikey': str(his_url),'curkey': str(his_url),'from': '1','appid': '311','typeid': '0','abstime': str(times),'fid': str(his_url).split('/')[-1],'active': '0','fupdate': '1'}url = 'https://user.qzone.qq.com/proxy/domain/w.qzone.qq.com/cgi-bin/likes/internal_dolike_app?'url = url + urllib.parse.urlencode(data)html = requests.post(url,headers=headers,cookies=cookie,data=post_data)if html.status_code == 200:print("点赞成功" if len(html.text) == 469 else "点赞失败")功能提升到秒赞因为树莓派并不是很不错的问题 , 这个代码做不到绝对的秒赞 。
在本地建立一个文件 , 负责写入最后一条说说所产生的时间戳 。比对当前时间戳与空间第一条说说是否相同 , 若相同则无更新 。点赞后重写文件 , 以便下次使用代码即可秒赞 。def run_tolike():if os.path.exists('time_out.txt'):with open('time_out.txt','r') as f:time_out = f.read()else:time_out = Nonewhile True:get_friends_list()time.sleep(__import__('random').randint(0,5)) # 秒赞?if not time_out or time_out != time_out:time_out = time_outget_zan(times,his_url)return Trueelse:log('说说无更新,等待中...')with open('time_out.txt','w') as f:f.write(str(times))全部代码import time,os,jsonimport reimport demjsonimport urllibimport requestsfrom lxml import etreedef log(content):this_time = time.strftime('%H:%M:%S',time.localtime(time.time()))print("["+str(this_time)+"]" + content)class QQ_like:def __init__(self,qq_number):self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}self.qq_number = qq_numberself.get_preparameter()self.run_tolike()def get_preparameter(self):self.search_cookie()self.get_g_tk()self.get_space()def run_tolike(self):if os.path.exists('time_out.txt'):with open('time_out.txt','r') as f:self.time_out = f.read()else:self.time_out = Nonewhile True:self.get_friends_list()time.sleep(__import__('random').randint(0,5))def search_cookie(self):if not os.path.exists('cookie_dict.txt'):self.get_cookie_json()with open('cookie_dict.txt', 'r') as f:self.cookie=json.load(f)return Truedef get_cookie_json(self):password = __import__('getpass').getpass('请输入密码:')from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionslogin_url = 'https://i.qq.com/'chrome_options =Options()chrome_options.add_argument('--headless')driver = webdriver.Chrome(options=chrome_options)driver.get(login_url)driver.switch_to_frame('login_frame')driver.find_element_by_xpath('//*[@id="switcher_plogin"]').click()time.sleep(1)driver.find_element_by_xpath('//*[@id="u"]').send_keys(self.qq_number)driver.find_element_by_xpath('//*[@id="p"]').send_keys(password)time.sleep(1)driver.find_element_by_xpath('//*[@id="login_button"]').click()time.sleep(1)cookie_list = driver.get_cookies()cookie_dict = {}for cookie in cookie_list:if 'name' in cookie and 'value' in cookie:cookie_dict[cookie['name']] = cookie['value']with open('cookie_dict.txt', 'w') as f:json.dump(cookie_dict, f)return Truedef get_g_tk(self):p_skey = self.cookie['p_skey']h = 5381for i in p_skey:h += (h << 5) + ord(i)self.g_tk = h & 2147483647def get_space(self):your_url = 'https://user.qzone.qq.com/' + str(self.qq_number)html = requests.get(your_url,headers=self.headers,cookies=self.cookie)if html.status_code == 200:self.qzonetoken = re.findall('window.g_qzonetoken =(.*?);',html.text,re.S)[1].split('"')[1]return Truedef get_friends_list(self):times = ""url = "https://user.qzone.qq.com/proxy/domain/ic2.qzone.qq.com/cgi-bin/feeds/feeds3_html_more?"data = https://www.hedan60.com/baike2/{'uin': self.qq_number,'scope': '0','view': '1','daylist': '','uinlist': '','gid': '','flag': '1','filter':'all','applist': 'all','refresh': '0','aisortEndTime': '0','aisortOffset': '0','getAisort': '0','aisortBeginTime': '0','pagenum': '1','externparam': 'undefined','firstGetGroup': '0','icServerTime': '0','mixnocache': '0','scene': '0','begintime': 'undefined','count': '10','dayspac': 'undefined','sidomain': 'qzonestyle.gtimg.cn','useutf8': '1','outputhtmlfeed': '1','rd': '0.9311604844249088','usertime': str(round(time.time() * 1000)),'windowId': '0.51158950324406','g_tk': self.g_tk,'qzonetoken': self.qzonetoken,}url = url + urllib.parse.urlencode(data) + '&g_tk=' + str(self.g_tk)html = requests.get(url,headers=self.headers,cookies=self.cookie)if html.status_code == 200:text = html.text[10:-2].replace(" ", "").replace('n','')json_list = demjson.decode(text)['data']['data']qq_spaces = json_list[0]content = str(qq_spaces['html'])try:zanshu = re.findall('(.*?)人觉得很赞
',content,re.S)[0]except:return Nonetime_out = str(qq_spaces['feedstime'])log("名字:"+str(qq_spaces['nickname']))log("QQ号:"+str(qq_spaces['opuin']))log("时间:"+time_out)log('赞数:'+zanshu)times = qq_spaces['abstime']his_url = re.findall('data-curkey="(.*?)"',content,re.S)[0]if not self.time_out or self.time_out != time_out:self.time_out = time_outself.get_zan(times,his_url)return Trueelse:log('说说无更新,等待中...')else:log(html.status_code)def get_zan(self,times,his_url):data = {'g_tk': self.g_tk,'qzonetoken': self.qzonetoken}post_data = {'qzreferrer': 'https://user.qzone.qq.com/'+str(qq_number),'opuin': str(qq_number),'unikey': str(his_url),'curkey': str(his_url),'from': '1','appid': '311','typeid': '0','abstime': str(times),'fid': str(his_url).split('/')[-1],'active': '0','fupdate': '1'}url = 'https://user.qzone.qq.com/proxy/domain/w.qzone.qq.com/cgi-bin/likes/internal_dolike_app?'url = url + urllib.parse.urlencode(data)html = requests.post(url,headers=self.headers,cookies=self.cookie,data=post_data)if html.status_code == 200:log("点赞成功" if len(html.text) == 469 else "点赞失败")with open('time_out.txt','w') as f:f.write(str(times))if __name__ == "__main__":qq_number = input('请输入qq号:')QQ_like(qq_number)