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

使用Python爬取QQ好友的说说

程序员文章站 2022-04-26 08:09:54
...

个人博客
前几天把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=×××××)
使用Python爬取QQ好友的说说

点击preview 会发现里面就是我们需要的信息
使用Python爬取QQ好友的说说

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

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完成的 步骤后续添加

相关标签: 爬虫