目录

 

一、前言

二、利用selenium模拟登陆获取cookie并保存到本地

三、破解空间加密参数g_tk

四、在个人QQ空间好友栏获取好友列表

五、获取好友空间说说的json文件,获取姓名、说说内容、时间等信息,存入数据库

六、开启多线程爬取

七、小结

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!??¤
QQ群:623406465


一、前言

玩了这么多年QQ,学了爬虫当然要爬一下啦,肯定有大佬要说爬个QQ空间还要多线程吗,人家只是刚看了多线程方面的知识想用一下啦*٩(๑´∀`๑)ง*。第一次写博客,希望有大佬能指出不足。

二、利用selenium模拟登陆获取cookie并保存到本地

PS:很多朋友问我QQ空间现在用这个方法登录有滑动验证码,但是论文+复试=繁忙,所以提供一个简单的方法:

1、手动登录自己的QQ空间,然后F12->Network,随便点一个链接,手动复制下右边Headers里边的cookie

2、到python里运行下把cookie转字典的代码

cookie = '刚刚手动复制的cookie'
# 字符串cookie转字典格式
cookie_dict = {}
for i in cookie.split('; '):
    cookie_dict[i.split('=')[0]] = i.split('=')[1]
print(cookie_dict)

 

效果如下:

3、获取g_tk

用selenium打开https://i.qq.com/,可以选择直接点击已登陆的QQ头像登陆或者选择账号密码登陆,这里我采用账号密码登陆获取cookie,需要注意的是登陆界面是在一个iframe里面,需要先切换到这个iframe里面然后才能点击输入账号密码以及登陆等操作。

这里我选择把它保存到本地的txt文件中,方便从文件中直接读取。具体获取cookie的代码如下:

from selenium import webdriver
import time
import json
 
qq_number = '********'
password = '********'
 
login_url = 'https://i.qq.com/'
driver = webdriver.Chrome()
driver.get(login_url)
#进入登陆的ifame
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)

 

三、破解空间加密参数g_tk

我选择使用QQ空间中好友栏获取所有的好友列表,很容易就可以在network里边发现有个好友列表的json格式的链接

这么舒服的嘛

不多哔哔,先发送个请求再说

headers有了啊,cookies也有了啊,403?!

这可咋整,俗话说遇事不决问百度,度娘的回答是参数中的g_tk是空间加密的一个参数,要想正确访问就要把这个加密的值算出来,加密算法在一个js中。

打开这个文件看看,哇,怎么是一片奇奇怪怪的代码,点一下Sources 面板下方的 pretty print 按钮{}就可以把JavaScript的代码格式化了。然后Ctrl+F找一下这个g_tk,发现他的值是QZFL.pluginsDefine.getACSRFToken()函数返回的结果,再次Ctrl+F找到了这个函数的位置。

QZFL.pluginsDefine.getACSRFToken()函数获取cookie中的p_sky的值,QZFL.pluginsDefine.getACSRFToken._DJB()函数将这个值通过与5381位运算算来算去得到一个值,这个值就是我们要的g_tk,将这段代码改成我们要用的python代码:

def get_g_tk():
    p_skey = cookie_dict['p_skey']
    h = 5381
    for i in p_skey:
        h += (h << 5) + ord(i)
        g_tk = h & 2147483647
    print('g_tk', g_tk)
    return g_tk

 

四、在个人QQ空间好友栏获取好友列表

搞定了g_tk,接下来我们就只需要进刚才所说的空间好友栏页面将所有的好友的QQ号抓下来,经过多次删减参数,得到相关参数只有三个data = {'uin': 1525943131, 'do': 1, 'g_tk': g_tk},用urllib.parse.urlencode(data)将参数转成我们常见的url后面缀了一长串&&&的形式与原始链接拼接,然后就可以带上cookies发送请求获取json数据,小做处理得到好友QQ号列表:

def get_friends_uin(g_tk):
    yurl = 'https://user.qzone.qq.com/proxy/domain/r.qzone.qq.com/cgi-bin/tfriend/friend_ship_manager.cgi?'
    data = {
            'uin': 1525943131,
            'do': 1,
            'g_tk': g_tk
            }
    url = yurl + urllib.parse.urlencode(data)
    res=requests.get(url, headers = headers, cookies = cookie_dict)
    r = res.text.split('(')[1].split(')')[0]
    friends_list=json.loads(r)['data']['items_list']
    friends_uin=[]
    for f in friends_list:
        friends_uin.append(f['uin'])
    return friends_uin

 

五、获取好友空间说说的json文件,获取姓名、说说内容、时间等信息,存入数据库

点进好友空间,点击说说,我们在network里可以看到有这样一个链接:

双击打开,我们会发现这是好友发的说说的json数据,有json数据就很好办呀,删减参数发现控制说说翻页的参数是pos,每一页最多20条,pos从0开始,每翻一页增加20,构造链接,发送请求,获取数据,小做处理,得到内容时间等信息,设计数据库,这里需要注意的是QQ号最好用bigint类型,不然有可能会超出int类型的最大范围,content的字符集选用utf8mb4,因为QQ上Emoji表情或者某些特殊字符是4个字节,MySQL的utf8编码最多三个字节:

还有几个细节:好友的说说中有可能会有单引号、斜杠、反斜杠等奇奇怪怪的符号存在,会报错,因此在存之前对content做pymysql.escape_string(content)的处理,escape_string函数会自动帮我们转义这些特殊字符;好友如果设置了拒绝访问,一定要拿小本本记下来!

具体代码如下:

def get_dynamic(uin):
    print(uin)
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="123456", db='my_sql', charset='utf8mb4')
    cursor = conn.cursor()
    yurl = 'https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?'
    pos = 0
    while True:
        data = {
                'uin': uin,
                'pos':pos,
                'num':20,
                'replynum':100,
                'callback':'_preloadCallback',
                'code_version':1,
                'format':'jsonp',
                'need_private_comment':1,
                'g_tk': g_tk
                }
        url = yurl + urllib.parse.urlencode(data)
        res=requests.get(url,headers = headers, cookies = cookie_dict)
        r = re.findall('((.*))',res.text)[0]
        dynamic = json.loads(r)
        pos += 20
        if 'msglist' in dynamic:
            msglist=dynamic['msglist']
            if msglist:
                for m in msglist:
                    name=m['name']
                    content=pymysql.escape_string(m['content'])
                    created_time=m['created_time']
                    standard_time=time.localtime(created_time)
                    standard_time = time.strftime("%Y-%m-%d %H:%M:%S", standard_time)
                    sql = "insert into qzone_spider(qq_number, name, created_time, content) values (%d, '%s', '%s', '%s')"
                    data = (uin, name, standard_time, content)
                    try:
                        cursor.execute(sql % data)
                    except Exception as e:
                        print(e)
                    conn.commit()
            else:
                print("没有更多的说说了╮(︶﹏︶)╭")
                break
        else:
            print("好友空间没有对我开放(。・ˇ_ˇ・。:)")
            access_denied.append(uin)
            break

 

六、开启多线程爬取

多线程的理解我认为就是一个人要干很多个人的活,为了加快速度,没办法喽╮(╯_╰)╭

#设置线程池容量,创建线程池
pool_size = 10
pool = threadpool.ThreadPool(pool_size)
#创建工作请求
reqs = threadpool.makeRequests(get_dynamic, friends_uin)
#将工作请求放入队列
[pool.putRequest(req) for req in reqs]
#for req in requests:
#    pool.putRequest(req)
pool.wait()

 

200位好友,一共四万七千多条数据数,速度蛮快,效果如下:

其中居然有21位好友的空间拒绝对我开放!太让人心痛了。

 

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/sn8888/p/13864007.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!