欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

爬取qq好友说说并对数据简单分析

程序员文章站 2022-03-07 19:52:06
...

看了网上大神和相关书本的操作,自己实践并改变了一些。我把我的思路和细节写出来。写的不好多多指教。
我用了两种方法爬取数据重点内容,一个是直接爬取,另一个是利用Selenium模拟
第一种:使用Google Chrome浏览器,打开网页版qq登录界面,在登录之前按F12

爬取qq好友说说并对数据简单分析

输入账号密码登录后点击说说,在右侧Google Chrome开发者工具中选择Network,Filter右侧选择XHR,可以筛选掉很多加载的文件,在Name下面查看一个前缀为”emotion_cgi_msglist_v6“的文件,点击后在右侧Headers中找到Request Headers,复制下面所有的内容(标签前面的:去掉),关掉Request Headers,在下面Query String Parameters中复制uin和g_tk。这样我们就把爬取所需要的三个关键东西准备好了,更换这三个东西就可以爬取不同qq号的好友说说。

爬取qq好友说说并对数据简单分析

说明一下在写脚本之前的功课,在Query String Parameters的format中可以看到是jsonp,说明这个网页返回的是json格式的数据,点击Headers的右侧的Preview查看返回的数据

爬取qq好友说说并对数据简单分析

我们需要爬取的数据包括msglist(发表说说的信息),total(只需要爬取一次就可以,total代表发表说说的总数量,和真实数量有区别,因为有些说说已经被删除)。提一句,num为网页返回的说说的数量信息,单次请求超过40后会只返回10条。点开msglist,里面包含数量为num的说说的信息,点开其中的某一个,有若干信息,我们需要爬取的包括cmtnum(评论的数量),commentlist(评论人的信息),content(说说的内容),createTime(创建说说的时间),name(发表人name),uin(*发表人qq,后
面构建url时需要用到),tid(构造获取点赞信息的url*)。这样返回的json数据是一页的,我们需要构建不同页的好友说说的url。观察并去掉一些字符后,最终我们可以得到这样的格式:
https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?uin= A &pos=B&num=20&g_tk=C
A填我们上面的得到的uin,C填复制的g_tk,B的填法(和num的值有关)是:0代表第一页(即从第一条说说到第二十条说说),20代表第二页,以此类推

返回的信息不包括点赞的信息,点赞的信息有另外的网页返回返回数据。
我们看一下啊,首先在某一条说说中点击”某某多少人觉得很赞”,出现如下图的内容

爬取qq好友说说并对数据简单分析

在右侧出现了一个前缀为”get_like_list_app“的文件,点击Preview查看返回的数据格式,data是返回的点赞信息,点开data,需要爬取的信息包括total_number(点赞数量,和显示的点赞有区别,原因可能是有些点赞被撤回),like_uin_info(点赞人的信息),点开后可以看到addr(地址),constellation(星座),fuin(点赞人的qq),gender(性别),if_qq_friend(是否是好友),if_special_care(不大清楚是什么),if_special_vip(是否是vip),nick(昵称)

构建点赞信息的url,方法与上面类似,最终得到格式如下:
https://user.qzone.qq.com/proxy/domain/users.qzone.qq.com/cgi-bin/likes/get_like_list_app?uin=A&unikey=B&begin_uin=0&query_count=60&if_first_page=1&g_tk=C
A填我们复制的uin(注意不是爬取的),B填构造好的点赞url(构造格式为:http://user.qzone.qq.com/D/mood/E.1,D填爬取的uin,E填爬取的tid),C填复制的g_tk。

在爬取之前还需要一件准备工作,需要得到好友列表,这样我们才知道要爬取那些人的说说。介绍两种方法。在这里先介绍第一种,在第二种爬取方法中介绍第二种。
这时候看Google Chrome 开发者工具Name下面有一个前缀为”friend_hat_get.cgi“的文件,复制Headers中General下Request URL的值,这就是我们爬取好友列表信息需要的url。查看它的Preview,会发现它返回的是好友列表,我们需要爬取的包括data下面的列表名(即qq号)和realname(应该是备注)。

爬取qq好友说说并对数据简单分析

使用的软件是PyCharm,需要的库为requests(请求网页),json(解析返回的json格式的数据),multiprocessing(多进程),pymongo(存储说说的数据库)

#导入依赖的库
import requests
import json
from multiprocessing import Pool
import pymongo
#浏览器的头
headers = {
#填写复制的信息
}
ownQQ = '
#复制的uin
'
g_tk = '
#复制的g_tk
'
url = '
#复制的url
'
#本地数据库
client = pymongo.MongoClient('localhost',27017)
#数据库名 Qzone2
mydb = client['Qzone2']

#好友列表
QQs = mydb[ownQQ+'QQs']
#存取说说信息
qzone = mydb[ownQQ+'qzone']

#第一步 爬取好友列表
def getFriends(url):
    html = requests.get(url,headers=headers)
    #因为返回的数据格式不符合json,需要处理一下
    #91可能会有所变化 如果格式不对 自己打印查看然后改进一下
    #测试json格式是否正确的网站:http://www.bejson.com/
    response = '[' + html.text[10:][:-90] + '}}}]'
    # print(response)
    #解析json数据
    json_Data = json.loads(response)[0]
    for d in json_Data['data']:
        qq = d
                try:
            name = json_Data['data'][qq]['realname']
            info = {
                'qq':d,
                'realname':name
            }
        except:
            info = {
                'qq':d,
                'realname':''
            }
        QQs.insert_one(info)

#第二步 爬取信息
def getInfos(qq):
    #没有权限的跳过
    try:
        url = 'https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?uin=' + qq + '&pos=0&num=20&g_tk='+ g_tk
        html = requests.get(url, headers=headers)
        # 格式处理
        response = '[' + html.text[10:][:-2] + ']'
        json_Data = json.loads(response, encoding='utf-8')[0]
        total = json_Data['total']
        for pos in range(0, int(total), 20):
            url = 'https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?uin=' + qq + '&pos=' + str(
                pos) + '&num=20&g_tk=' + g_tk
            html = requests.get(url, headers=headers)
            # 格式处理
            response = '[' + html.text[10:][:-2] + ']'
            json_Data = json.loads(response, encoding='utf-8')[0]
            msglist = json_Data['msglist']
            if msglist != None:
                for msg in msglist:
                    # 评论数量
                    cmtnum = msg['cmtnum']
                    # 说说内容
                    Scontent = msg['content']
                    # 发表时间
                    timeShuo = msg['createTime']
                    comments = []
                    if cmtnum:
                        # 评论人员列表
                        commentlist = msg['commentlist']
                        for comment in commentlist:
                            # 评论人qq
                            qq_comment = comment['uin']
                            # nickname
                            # name = comment['name']
                            # 评论时间
                            createTime = comment['createTime']
                            createTime2 = comment['createTime2']
                            # 内容
                            # content = comment['content']
                            comments.append('{ "qq_comment":"' + str(
                                qq_comment) + '","createTime":"' + createTime + '","createTime2":"' + createTime2 + '"}')
                    tid = msg['tid']
                    # 构造说说url
                    Surl = 'http://user.qzone.qq.com/' + qq + '/mood/' + tid + '.1'
                    Like = get_likes(Surl)
                    data = {
                        'qq': qq,
                        'content': Scontent,
                        'createTime': timeShuo,
                        'cmtnum': cmtnum,
                        'comment': comments,
                        'like_number': Like['like_number'],
                        'like_info': Like['like_info']
                        }
                    qzone.insert_one(data)
    except:
        print('error')
        pass

#获取点赞信息
def get_likes(url):
    #根据传入的说说地址 构造获取点赞信息的url
    url = 'https://user.qzone.qq.com/proxy/domain/users.qzone.qq.com/cgi-bin/likes/get_like_list_app?uin='+ownQQ+'&unikey='+\
          url+'&begin_uin=0&query_count=60&if_first_page=1&g_tk='+g_tk
    html = requests.get(url,headers=headers)
    #网页编码转换为unicode
    html.encoding='unicode'
    # 格式处理
    response = '[' + html.text[10:][:-3] + ']'
    json_Data = json.loads(response)[0]['data']
    total_number = json_Data['total_number']
    likes = []
    if total_number:
        like_uin_info = json_Data['like_uin_info']
        for info in like_uin_info:
            addr = info['addr']
            constellation = info['constellation']
            fuin = info['fuin']
            gender = info['gender']
            if_qq_friend = info['if_qq_friend']
            if_special_care = info['if_special_care']
            is_special_vip = info['is_special_vip']
            # nick = info['nick']
            likes.append('{ "addr":"'+addr+'","constellation":"'+constellation+'","fuin":"'+str(fuin)+'","gender":"'+gender+
                         '","if_qq_friend":"'+str(if_qq_friend)+'","if_special_care":"'+str(if_special_care)+'","is_special_vip":"'+str(is_special_vip)+'"}')
            likes.append('{ "fuin":"'+str(fuin)+'"}')
    data = {
        'like_number':total_number,
        'like_info':likes
    }
    return data
if __name__ == '__main__':
# 每次使用,更新headers中的cookie或者全部更新headers 和 g_tk
#换号时更新headers ownQQ 和g_tk
    getFriends(url)
    QQ = [item['qq'] for item in QQs.find()]
    pool = Pool(processes=4)
    pool.map(getInfos,QQ)

下篇再续

相关标签: 爬虫