动态爬虫之qzone空间自动秒赞 - qq空间自动点赞

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞

步骤

1、分析列表请求
2、分析请求参数
3、分析点赞请求
4、分析点赞参数
5、编写执行代码

我们上次分析过 动态爬虫之QQ好友列表获取 今天这篇继续按照上次的思路来,如果您看过我上篇建议您直接看参数按照以前的操作就好。

1、分析列表请求

首先我们还是打开这个网址 https://h5.qzone.qq.com/mqzone/index 并且登陆

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第1张图片

打开chrome 调试工具,找到拦截请求这一块刷新一下页面(为了页面排版,我只截取了一小部分)

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第2张图片

然而并没有发现与动态相关代码因为qzone 为了减少客户端的渲染压力提高用户体验,第一次直接在服务端进行渲染返回了
既然是服务端加载而我们又不想消耗很多性能,那只有看一下加载下一页的数据返回是否是服务器渲染 将页面拉到最底部,清空拦截的数据,然后点击加载更多。

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第3张图片

这边就看到了qzone动态列表的这个请求

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第4张图片

2、分析请求参数

query string parameter
qzonetoken
g_tk
form data
res_type 固定 0
res_attach
refresh_type 固定2
format 固定json
attach_info


这边 qzonetoken 和 g_tk 跟上次一样,我就直接复制过来了

var qzonetoken = window.shine0callback
var g_tk =  window.user.getToken()

这边只剩下两参数,仔细的你会看出两个参数其实值是一样的 百度霸屏

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第5张图片

所以我们只需要找一个参数就可以取到动态列表(其实在登陆情况下直接 get 请求链接也是可以取到动态的)
这边我们来搜索一下 res_attach 这个参数

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第6张图片

有没有熟悉的味道,没错又是放在静态页面中的 FrontPage 里面,所以直接拿出来(注意:在静态页面中提取出来的只能第一次使用,每次请求接口服务器都会返回新的)

var res_attach = FrontPage.data.data.attachinfo

3、分析点赞请求

先刷新动态页面,然后选择第一条进行点赞,查看拦截

动态爬虫之qzone空间自动秒赞 - qq空间自动点赞_第7张图片

发现 url 中必有 qzonetoken 和 g_tk 这边分析一下post的参数就好了

4、分析点赞参数

这边就不讲 qzonetoken 和 g_tk 了因为这两个参数上面就说过了怎么拿过来 (这边只管发说说的,不管分享的链接和其他的)
form data
opuin:* 点赞的账号 也就是你当前登录的qq 号
unikey:http://user.qzone.qq.com/\
**/mood/18623a5f8da5715907360500
curkey: http://user.qzone.qq.com/\*\*\*/mood/18623a5f8da5715907360500
appid: 固定 311 http://qq.gam7.com
opr_type:固定 like
format:固定 purejson

先找一下 unikey 看下这个参数 (unikey 和 curkey 值很多时候是一样的,如果是转发的说说,这两个参数就不一样了,所以不要偷懒)

发现参数是在一个 comm.orglikekey 直接在动态列表数据里面搜索 orglikekey 字段 result.data.vFeeds.comm.orglikekey

直接搜索 curlikekey 发现是在 orglikekey的下面一条 curlikekey

5、编写执行代码

先把这些参数都取过来

 # 获取动态列表参数
def paresHtml(self):
    qzonetoken = self.driver.execute_script('return window.shine0callback')
    g_tk = self.driver.execute_script('return window.user.getToken()')
    res_type = '0'
    res_attach = self.driver.execute_script('')
    refresh_type = '2'
    attach_info = res_attach
    format = 'json'

 

 拼接参数执行返回结果 这边记住 post 请求一定要设置 XMLHttpRequest 的 withCredentials = true

def sendRequest(self, url, method, data):
        cname = 'request_%d' % time.time()
        self.driver.execute_script('window.%s = new XMLHttpRequest;' % cname)
        self.driver.execute_script('window.%s.withCredentials=true;' % cname)
        self.driver.execute_script(
            'window.%s.open(\'%s\',\'%s\',false)' % (cname, method, url))
        self.driver.execute_script(
            'window.%s.onload = function (e){window.%s = window.%s.responseText;}' % (
                cname, ('%s_result' % cname), cname))
        self.driver.execute_script(
            'window.%s.send("%s")' % (cname, data))
        return self.driver.execute_script('return window.%s' % ('%s_result' % cname))
sctiveFeeds = 'https://h5.qzone.qq.com/webapp/json/mqzone_feeds/getActiveFeeds?qzonetoken=%s&g_tk=%s' % (
            qzonetoken, g_tk)
# 执行请求,并且返回结果
        result = json.loads(self.sendRequest(sctiveFeeds, 'POST',
                                             'res_type=%s&res_attach=%s&refresh_type=%s&format=%s&attach_info=%s' % (
                                                 res_type, res_attach, refresh_type, format, attach_info)))

 由于数据量庞大所以返回可能会慢一点 现在开始造点赞的参数

opuin = self.driver.execute_script('return user.getUin()')
unikey = result['data']['vFeeds'][0]['comm']['orglikekey']
curkey = result['data']['vFeeds'][0]['comm']['curlikekey']
appid = result['data']['vFeeds'][0]['comm']['appid']
opr_type = 'like'
format = 'purejson'
liked = not 1 == result['data']['vFeeds'][0]['like']['isliked']
# 是否已经点赞,如果是那就不调用
if liked:
    dolike = 'https://h5.qzone.qq.com/proxy/domain/w.qzone.qq.com/cgi-bin/likes/internal_dolike_app?qzonetoken=%s&g_tk=%s' % (
            qzonetoken, g_tk)
    result = json.loads(self.sendRequest(dolike, 'POST',
                        'opuin=%s&unikey=%s&curkey=%s&appid=%s&opr_type=%s&format=%s' % (
                            opuin, unikey, curkey, appid, opr_type, format)))

完整代码

qq全自动秒点赞 但是登陆验证码需要自己输入 这边js可能会导致phantomjs内存泄漏,所以我过两个小时会把 phantomjs 关闭

import json
import os
import pickle
import platform
import time
import urllib
from _sha1 import sha1
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import DesiredCapabilities, ActionChains
class qzone_dlewares(object):
    # 浏览器请求头
    headers = {'Accept': '*/*',
               'Accept-Language': 'en-US,en;q=0.8',
               'Cache-Control': 'max-age=0',
               'User-Agent': 'Mozilla/5.0 (Linux; U; Android 2.3.6; zh-cn; GT-S5660 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MicroMessenger/4.5.255',
               'Connection': 'keep-alive', }
    webdriverPath = 'E:\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe'
    attachinfo = False
    # 初始化浏览器
    def __init__(self, userName='', password='', *args, **kwargs):
        self.userName = userName
        self.password = password
        desired_capabilities = DesiredCapabilities.PHANTOMJS.copy()
        for key, value in self.headers.items():
            desired_capabilities['phantomjs.page.customHeaders.{}'.format(key)] = value
        # 禁止加载图片
        desired_capabilities["phantomjs.page.settings.loadImages"] = False
        self.driver = webdriver.PhantomJS(executable_path=self.webdriverPath, desired_capabilities=desired_capabilities)
        # 设置屏幕大小
        self.driver.set_window_size(414, 736)
    # 开始请求并且截图
    def startQzoneRequest(self):
        # 开始请求qzone
        self.driver.get('https://mobile.qzone.qq.com')
        # 截图保存到当前项目下
        self.driver.save_screenshot('screenshot.png')
    # 判断是否登录了
    def isLogin(self):
        try:
            u = self.driver.find_element_by_xpath('//*[@id="u"]')
            p = self.driver.find_element_by_xpath('//*[@id="p"]')
            go = self.driver.find_element_by_xpath('//*[@id="go"]')
        except NoSuchElementException:
            return True
        return False
    def loginQzone(self):
        u = self.driver.find_element_by_xpath('//*[@id="u"]')
        p = self.driver.find_element_by_xpath('//*[@id="p"]')
        go = self.driver.find_element_by_xpath('//*[@id="go"]')
        # 清理账号和密码
        u.clear()
        p.click()
        # 移动到账号框模仿键盘输入账号
        action = ActionChains(self.driver)
        action.move_to_element(u)
        action.click(u)
        # 模仿键盘输入账号
        action.send_keys(self.userName)
        # 移动到密码输入框
        action.move_to_element(p)
        action.click(p)
        # 模仿键盘输入密码
        action.send_keys(self.password)
        # 点击登录
        action.move_by_offset(go.location['x'], go.location['y'])
        action.click(go)
        # 执行登录
        action.perform()
        # 休息1秒保证能执行
        time.sleep(1)
        # 截图保存到当前项目下
        self.driver.save_screenshot('screenshotLoginQzone.png')
    def save_verify_code(self, element):
        url = element.get_attribute('src')
        fileName = element.get_attribute('id') + '.jpg'
        urllib.request.urlretrieve(url, fileName)
    # 校验码
    def check_code(self):
        # 先切换到默认的窗口
        self.driver.switch_to.default_content()
        iframe = None
        try:
            # 验证码
            iframe = self.driver.find_element_by_xpath('//*[@id="new_vcode"]/iframe[2]')
        except NoSuchElementException:
            print('无需输入验证码')
        else:
            self.driver.switch_to.frame(iframe)
            self.verify_code()
    # 验证码
    def verify_code(self):
        que_code = self.driver.find_element_by_xpath('//*[@id="cap_que_img"]')
        que_input = self.driver.find_element_by_xpath('//*[@id="cap_input"]')
        que_but = self.driver.find_element_by_xpath('//*[@id="verify_btn"]')
        # 保存验证码
        self.save_verify_code(que_code)
        verify_path = que_code.get_attribute('id') + '.jpg'
        # 输入验证码
        if (self.isWindows()):
            os.startfile(verify_path)
        else:
            os.subprocess.call(["xdg-open", verify_path])
        input_verify_code = input("验证码:")
        # 模仿用户输入
        action = ActionChains(self.driver)
        action.move_to_element(que_input)
        action.click()
        action.send_keys(input_verify_code)
        action.move_to_element(que_but)
        action.click()
        # 执行
        action.perform()
    def paresHtml(self):
        time.sleep(1)
        # 切换到默认的容器
        self.driver.switch_to.default_content()
        # 获取动态列表参数
        qzonetoken = self.driver.execute_script('return window.shine0callback')
        g_tk = self.driver.execute_script('return window.user.getToken()')
        res_type = '0'
        res_attach = self.attachinfo and self.attachinfo or self.driver.execute_script(
            'return window.FrontPage.data.data.attachinfo')
        refresh_type = '2'
        attach_info = res_attach
        format = 'json'
        # 动态列表
        sctiveFeeds = 'https://h5.qzone.qq.com/webapp/json/mqzone_feeds/getActiveFeeds?qzonetoken=%s&g_tk=%s' % (
            qzonetoken, g_tk)
        # 执行请求,并且返回结果
        resultStr = next(self.sendRequest(sctiveFeeds, 'POST',
                                          'res_type=%s&res_attach=%s&refresh_type=%s&format=%s&attach_info=%s' % (
                                              res_type, res_attach, refresh_type, format, attach_info)))
        result = json.loads(resultStr)
        print(resultStr)
        # 判断数据是否正确
        if result['ret'] == 0 and result['code'] == 0:
            self.attachinfo = result['data']['attachinfo']
            for item in result['data']['vFeeds']:
                self.paresLikeList(item, qzonetoken, g_tk)
        else:
            print(result['message'])
        resultStr = None
        result.clear()
    def paresLikeList(self, item, qzonetoken, g_tk):
        # 点赞参数
        opuin = self.driver.execute_script('return user.getUin()')
        unikey = item['comm']['orglikekey']
        curkey = item['comm']['curlikekey']
        appid = item['comm']['appid']
        opr_type = 'like'
        format = 'purejson'
        likeresult = None
        # 是否已经点赞,如果是那就不调用
        liked = 'like' not in item or not 1 == item['like']['isliked']
        if liked:
            dolike = 'https://h5.qzone.qq.com/proxy/domain/w.qzone.qq.com/cgi-bin/likes/internal_dolike_app?qzonetoken=%s&g_tk=%s' % (
                qzonetoken, g_tk)
            likeresult = json.loads(next(self.sendRequest(dolike, 'POST',
                                                          'opuin=%s&unikey=%s&curkey=%s&appid=%s&opr_type=%s&format=%s' % (
                                                              opuin, unikey, curkey, appid, opr_type, format))))
        if (not likeresult == None) and likeresult['ret'] == 0:
            content = ''
            if 'summary' in item:
                content = item['summary']['summary']
            elif 'cell_summary' in item:
                content = item['cell_summary']['summary']
            elif 'original' in item:
                content = item['original']['cell_summary']['summary']
            else:
                content = '未知内容'
            print('点赞成功:%s %s' % (item['userinfo']['user']['nickname'], content))
        item.clear()
    def sendRequest(self, url, method, data):
        cname = 'request_%d' % time.time()
        self.driver.execute_script('window.%s = new XMLHttpRequest;' % cname)
        self.driver.execute_script('window.%s.withCredentials=true;' % cname)
        self.driver.execute_script(
            'window.%s.open(\'%s\',\'%s\',false)' % (cname, method, url))
        self.driver.execute_script(
            'window.%s.onload = function (e){window.%s = window.%s.responseText;}' % (
                cname, ('%s_result' % cname), cname))
        self.driver.execute_script(
            'window.%s.send("%s")' % (cname, data))
        yield self.driver.execute_script('return window.%s' % ('%s_result' % cname))
        # 内存回收
        self.driver.execute_script(' window.%s = undefined;window.%s = undefined;' % (('%s_result' % cname), cname))
    # 是 windows 系统
    def isWindows(self):
        sysstr = platform.system()
        if (sysstr == "Windows"):
            return True
        return False
    # 保存登录 cookies
    def save_cookies(self):
        with open(self.hashCode(), 'wb') as f:
            obj = self.driver.get_cookies()
            pickle.dump(obj, f)
            f.close()
    # 读取并设置 cookies
    def load_cookies(self):
        fileName = self.hashCode()
        # 判断文件是否存在
        if self.file_exists(fileName):
            f = open(fileName, 'rb')
            obj = pickle.load(file=f)
            f.close()
            # 循环设置 cookie
            try:
                for cookie in obj:
                    self.driver.add_cookie(cookie)
            except Exception as e:
                print(e)
    def delete_cookies(self):
        os.remove(self.hashCode())
    # hasCode
    def hashCode(self):
        sha = sha1()
        sha.update(b'qzone_cookies')
        return sha.hexdigest()
        # 判断文件是否存在
    def file_exists(self, filename):
        try:
            with open(filename) as f:
                return True
        except IOError:
            return False
    # 退出浏览器
    def __del__(self):
        self.driver.quit()
def startQzoneBaselanding():
    # 事先输入账号和密码
    userName = '***'
    password = '***'
    oldTime = time.time()
    browser = qzone_dlewares(userName=userName, password=password)
    # 加载cookies
    browser.load_cookies()
    initTime = time.time()
    # 打开浏览器并且截图
    browser.startQzoneRequest()
    requestTime = time.time()
    # 判断是否登录
    if (not browser.isLogin()):
        # 模仿用户登录
        browser.loginQzone()
        # 检查code
        browser.check_code()
    currentTime = time.time()
    # 解析动态
    browser.paresHtml()
    # 运行完成后再截图一次
    browser.driver.save_screenshot('screenshotLoginQzoneSuccess.png')
    # 保存cookies
    browser.save_cookies()
    print('开始时间 %f' % oldTime)
    print('结束时间 %f' % currentTime)
    print('初始化时间 %f' % (initTime - oldTime))
    print('加载页面时间 %f' % (requestTime - initTime))
    print('模仿操作时间 %f' % (currentTime - requestTime))
    print('总运行时间 %f' % (currentTime - oldTime))
    return browser
if __name__ == '__main__':
    # 第一次查询
    browser = startQzoneBaselanding()
    starttime = time.time()
    while True:
        # 两小时刷新
        currentTime = (time.time() - starttime) / 60 / 60
        if currentTime >= 2:
            browser.driver.quit()
            browser.delete_cookies()
            browser = startQzoneBaselanding()
            continue
        # 20秒刷新
        time.sleep(20)
        browser.paresHtml()

以上仅供参考学习。

你可能感兴趣的:(QQ营销软件)