使用Python爬取QQ好友的说说

个人博客
前几天把QQ好友的说说爬了下来 统计一下大概爬了有12W条数据 然后把这些数据进行了简单的可视化 分析完之后 突然想到可不可以把每个好友的进行分析 分析思路一样 只要前端输入相应的QQ 就能显示该QQ的分析结果 或者听同学的建议做一个随缘APP摇一摇手机就可看到其他人的说说 想想挺好玩儿 等有时间了把这个做了 完美


开发环境:

  • python3.5
  • MySQL5.7
  • Ubuntu16.04LTS
  • Python第三方库
  • selenium
  • Requests
  • pymysql
  • jieba
  • wordcloud

QQ空间爬虫步骤:

  1. 通过selenium+phantomjs模拟登录qq空间取到cookies和g_qzonetoken,并算出gtk(因为请求参数加密了)
  2. 通过Requests库通过前面获取的URL参数 构造http请求
  3. 分析请求响应 利用正则匹配出想要的字段(也可以用json库直接取)
  4. 根据匹配的信息设计数据库表 入库
  5. 通过qq邮箱的导出联系人功能 把好友QQ号导出csv文件 然后遍历所有的QQ号爬取所有的说说
  6. 后续的数据分析

代码实现

  • 通过selenium+phantomjs模拟登录qq空间取到cookies和g_qzonetoken,并算出gtk(因为请求参数加密了)
from selenium import webdriver
import time
import re


#获取cookie,g_tk,g_qzontoken这三个数据
def Login_QQ():
    '''gtk解密'''
    def getGTK(cookie):
        """ 根据cookie得到GTK """
        hashes = 5381
        for letter in cookie['p_skey']:
            hashes += (hashes << 5) + ord(letter)
        gtk=hashes&0x7fffffff
        return gtk

    browser=webdriver.Chrome()
    url = "https://qzone.qq.com/"  # QQ登录网址
    browser.get(url)

    browser.switch_to.frame('login_frame')#定位账号密码登录
    browser.find_element_by_id('switcher_plogin').click()

    browser.find_element_by_id('u').clear()
    browser.find_element_by_id('u').send_keys('')  # 这里填写你的QQ号
    browser.find_element_by_id('p').clear()
    browser.find_element_by_id('p').send_keys('')  # 这里填写你的QQ密码

    browser.find_element_by_id('login_button').click()
    time.sleep(1)
    print(browser.title)  # 打印网页标题
    # print(browser.get_cookies())
    cookie={}
    for element in browser.get_cookies():
        cookie[element['name']]=element['value']
    print('Get the cookie of QQlogin successfully!(共%d个键值对)' % (len(cookie)))
    print(cookie)
    html = browser.page_source  # 保存网页源码
    pattern = re.compile(r'window\.g_qzonetoken = \(function\(\)\{ try\{return "(.*?)";\}')
    g_qzonetoken=re.search(pattern,html)
    print(g_qzonetoken.group(1))
    gtk=getGTK(cookie)#通过getGTK函数计算gtk
    return (cookie,gtk,g_qzonetoken)


其实也可以用selenium的截屏功能进行扫码登录

通过Requests库利用前面得到的url参数,构造http请求

打开自己空间 然后开起浏览器开发者模式 点击XHR 和 Preservce log

然后在自己空间上点击说说 会发现这么一个URL(emotion_cgi_msglis_v6?uin=×××××)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3OjMKYFX-1589990125740)(http://p39e7cgx2.bkt.clouddn.com/%E7%88%AC%E5%8F%96QQ%E7%A9%BA%E9%97%B4.png)]

点击preview 会发现里面就是我们需要的信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N9NcYbN8-1589990125742)(http://p39e7cgx2.bkt.clouddn.com/%E7%88%AC%E5%8F%96QQ%E7%A9%BA%E9%97%B42.png)]

在该请求头中 会发现有两个参数是我们不确定的

g_tk
qzonetoken
其中g_tk是通过某个加密算法所生成的g_tk 具体讲解

而qzonetoken 可直接在网页源码中找到

获取构造的请求参数之后 即可构造url然后用正则提取需要的字段(因为觉得正则比较炫酷 所以就采用了正则)

def parse_mood(i):
'''从返回的json中,提取我们想要的字段'''
qq=get_qq()
text = re.sub('"commentlist":.*?"conlist":', '', i)
if text:
    myMood = {}
    myMood["isTransfered"] = False
    tid = re.findall('"t1_termtype":.*?"tid":"(.*?)"', text)[0]  # 获取说说ID
    tid = qq + '_' + tid
    myMood['id'] = tid
    myMood['pos_y'] = 0
    myMood['pos_x'] = 0
    mood_cont = re.findall('\],"content":"(.*?)"', text)
    if re.findall('},"name":"(.*?)",', text):
        name = re.findall('},"name":"(.*?)",', text)[0]
        myMood['name'] = name
    if len(mood_cont) == 2:  # 如果长度为2则判断为属于转载
        myMood["Mood_cont"] = "评语:" + mood_cont[0] + "--------->转载内容:" + mood_cont[1]  # 说说内容
        myMood["isTransfered"] = True
    elif len(mood_cont) == 1:
        myMood["Mood_cont"] = mood_cont[0]
    else:
        myMood["Mood_cont"] = ""
    if re.findall('"created_time":(\d+)', text):
        created_time = re.findall('"created_time":(\d+)', text)[0]
        temp_pubTime = datetime.datetime.fromtimestamp(int(created_time))
        temp_pubTime = temp_pubTime.strftime("%Y-%m-%d %H:%M:%S")
        dt = temp_pubTime.split(' ')
        time = dt[1]
        myMood['time'] = time
        date = dt[0]
        myMood['date'] = date
    if re.findall('"source_name":"(.*?)"', text):
        source_name = re.findall('"source_name":"(.*?)"', text)[0]  # 获取发表的工具(如某手机)
        myMood['tool'] = source_name
    if re.findall('"pos_x":"(.*?)"', text):
        pos_x = re.findall('"pos_x":"(.*?)"', text)[0]
        pos_y = re.findall('"pos_y":"(.*?)"', text)[0]
        if pos_x:
            myMood['pos_x'] = pos_x
        if pos_y:
            myMood['pos_y'] = pos_y
        idname = re.findall('"idname":"(.*?)"', text)[0]
        myMood['idneme'] = idname
        cmtnum = re.findall('"cmtnum":(.*?),', text)[0]
        myMood['cmtnum'] = cmtnum
    return myMood

获取数据之后入库
创建表

CREATE TABLE `mood` (
`name` varchar(80) DEFAULT NULL,
`date` date DEFAULT NULL,
`content` text,
`comments_num` int(11) DEFAULT NULL,
`time` time DEFAULT NULL,
`tool` varchar(255) DEFAULT NULL,
`id` varchar(255) NOT NULL,
`sitename` varchar(255) DEFAULT NULL,
`pox_x` varchar(30) DEFAULT NULL,
`pox_y` varchar(30) DEFAULT NULL,
`isTransfered` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

其实到这里主要的爬虫代码已经完了 之后是通过QQ邮箱的联系人导出功能 构造URL列表 就可以爬取所有好友的信息了(没有访客记录)我用单线程爬了大概3个小时
爬虫代码

mport pymysql
import re
import requests
import datetime
from qq.Login import Login_QQ
from qq.getFriends import getFriends
from qq.mood import parse_mood

host='localhost'
user=''
pwd=''
db=''

con=pymysql.connect(host,user,pwd,db,use_unicode=True, charset="utf8")#可中文入库
cursor=con.cursor()
con.autocommit(True)

# 伪造浏览器头
headers = {
    xxx
}

cookie,gtk,qzonetoken=Login_QQ()#通过登录函数取得cookies,gtk,qzonetoken
s=requests.session()#用requests初始化会话

friends=getFriends()

for qq in friends:#遍历qq号列表
    for p in range(0,1000):
        pos=p*20
        params={
        'uin':qq,
        'ftype':'0',
        'sort':'0',
        'pos':pos,
        'num':'20',
        'replynum':'100',
        'g_tk':gtk,
        'callback':'_preloadCallback',
        'code_version':'1',
        'format':'jsonp',
        'need_private_comment':'1',
        'qzonetoken':qzonetoken,
        'g_tk': gtk
        }

        response=s.request('GET','https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?',params=params,headers=headers,cookies=cookie)
        if response.status_code==200:
            text=response.text

            if not re.search('lbs',text):#通过lbs判断此qq的说说是否爬取完毕
                print("%s说说爬取完毕"%qq)
                break
            textlist=re.split('\{"certified"', text)[1:]
            for i in textlist:
                myMood=parse_mood(i)

                '''将提取的字段值插入mysql数据库,通过用异常处理防止个别的小bug中断爬虫,开始的时候可以先不用异常处理判断是否能正常插入数据库'''
                try:
                    # #去重
                    # same_sql = '''
                    #     select %s from mood
                    # '''
                    # cursor.execute(same_sql,myMood['id'])
                    # if  cursor.fetchall():
                    #     print("已经爬过该说说")
                    insert_sql = '''
                                          insert into mood(id,content,time,sitename,pox_x,pox_y,tool,comments_num,date,isTransfered,name)
                                          VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
                                       '''
                    cursor.execute(insert_sql, (
                    myMood['id'], myMood["Mood_cont"], myMood['time'], myMood['idneme'], myMood['pos_x'],
                    myMood['pos_y'], myMood['tool'], myMood['cmtnum'], myMood['date'], myMood["isTransfered"],
                    myMood['name']))

                except:
                    pass

print('说说全部下载完成!')

爬虫的内容结束 后面的数据分析 我是用Flask+Echarts完成的 步骤后续添加

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值