爬取QQ空间说说日志、好友个人信息并进行加密

项目背景、目的和意义

随着科学技术的不断发展,互联网进展的不断加快,人工智能、大数据和云计算等新兴技术的不断涌现,目前每天都有上亿的数据在网络中流通。而人工收集数据的发法效率低,成本高。因此,本项目利用Python爬虫等技术,能够在数分钟内,实现自动登录QQ空间,抓取个人信息、好友列表、说说和日志等信息,同时能够及时对抓取的数据进行加密,保证了通信安全。本项目的成功实施,对办公自动化、信息检索、互联网信息安全等方面具有重要意义,同时加以GUI界面进行封装,提高了程序的普适性和交互性。

业务说明

启动程序后,提示用户可供选择的操作:
1.抓取信息:继续提示输入QQ号和密码(密码不能显示出来,用*号代替),然后登录QQ空间,抓取其中的①QQ个人信息;②好友列表;③说说和日志;把获取到的信息经过加密后存入csv文件中。
2.显示信息:用户输入QQ号码后,生成解密的csv文件,用户可查看:①QQ个人信息;②好友列表;③说说和日志;输入Quit或quit可以退出系统。
在这里插入图片描述
在这里插入图片描述

代码实现:

1.GUI_main.py用户界面,用于运行程序

在这里插入图片描述
每一次抓取,都会为当前QQ建立一个文件夹,方便分类收集QQ的QQ空间中信息。

在这里插入图片描述
如果重复抓取,则会提醒用户已经抓取过了,此时可以选择删除该QQ的文件夹重新抓取或者显示信息。
如果想查看未抓取的QQ,则会提醒当前用户还未抓取过信息,此时可以选择输入该QQ的面进行抓取
在这里插入图片描述

具体代码如下:

import tkinter as tk
import tkinter.messagebox as Msg
from directory import mkdir
import os


window = tk.Tk()
window.title('QQ空间,分享生活,留住感动')
window.geometry('450x350')

# 欢迎界面
canvas = tk.Canvas(window, height=500, width=500)
image_file = tk.PhotoImage(file='demo.gif')
image = canvas.create_image(0,0, anchor='nw', image=image_file)
canvas.pack(side='top')

# 用户信息
tk.Label(window, text='Q Q ').place(x=50, y= 200)
tk.Label(window, text='密码 ').place(x=50, y= 230)
tk.Label(window, text='加密/解密秘钥 ').place(x=10, y= 260)

var_usr_name = tk.StringVar()
var_usr_name.set('在这里输入qq号')
entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
entry_usr_name.place(x=100, y=200)

var_usr_pwd = tk.StringVar()
entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')
entry_usr_pwd.place(x=100, y=230)


var_key = tk.StringVar()
entry_key = tk.Entry(window, textvariable=var_key)
entry_key.place(x=100, y=260)
var_key.set('请输入0-1000整数')

def get_all():
    """完成对内容的抓取和加密的过程"""
    
    username = var_usr_name.get()
    password = var_usr_pwd.get()
    key = var_key.get()
    file = username + "\\" + username + '_encrypted.csv'
    # 为当前用户创建文件夹
    if( not os.path.exists(username) or not os.path.exists(file)):
        # *************************爬取信息的主程序
        mkdir(username)
        import ourmain
        isSuccess = ourmain.main(username, password, key)
        if isSuccess:
            Msg.showinfo(message="信息已经抓取并加密完毕!")
        else:
            Msg.showinfo(message="账号或密码错误")
    else:
        Msg.showwarning(message="当前用户已经抓取过信息了!")
        return 
    
    
    
def show_all():
    """完成对内容的解密过程"""
    username = var_usr_name.get()
    path = username
    key = var_key.get()
   
    if(os.path.exists(path)):
        # ********************显示信息的主程序
        import decrypts1
        file0 = username + "\\" + username + '_encrypted.csv'
        file1 = username + "\\" + username + '_decrypted.csv'
        decrypts1.save_file(file0, file1, key)
        Msg.showinfo(message="信息解密完毕!")

    else:
        Msg.showerror(message="当前用户还未抓取过信息!")
        return 
    pass
    

# 按钮
btn_get = tk.Button(window, text='抓取信息', activeforeground = "black",activebackground = 'blue',command=get_all)
btn_get.place(x=100, y=300)
btn_show = tk.Button(window, text='显示信息', activeforeground = "black",activebackground = 'blue',command=show_all)
btn_show.place(x=200, y=300)
btn_quit= tk.Button(window,text = 'Quit',activeforeground = "black",activebackground = 'blue',command=window.destroy)
btn_quit.place(x=300, y=300)
window.mainloop()

2.ourmain.py 工程主程序

# -*- coding: utf-8 -*-

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from login import login1 as login
from friends import friends_lis
from information import get_information
from shuoshuo_wzq import get_shuoshuo
from encrypts0 import save_file
from rizhi_neirong_wzq import get_rizhi as neirong
from rizhi_timu_wzq import get_rizhi as timu

def main(username,password,key):
    login_url = 'https://qzone.qq.com/'
    driver = webdriver.Chrome(ChromeDriverManager().install())

    #driver = webdriver.Chrome(ChromeDriverManager().install())
    driver.get(login_url)
    
    if login(driver,username,password) == None:
        driver.quit()
        return False
    '''---------------------建立CSV文件--------------------''' 
    filename = username + "\\" + username + '.csv'
    file = open(filename,'w+',encoding='utf-8')
    
    '''---------------------爬取个人信息-------------------'''
    try:
        get_information(driver,file,username)
    except Exception as e:
        print(e)
        file.write('!!!!!个人信息抓取失败!!!!!\n')
    
    '''---------------------爬取好友列表-------------------'''
    try:
        friends_lis(driver,username,file)
    except Exception as e:
        print(e)
        file.write('\n!!!!!好友列表抓取失败!!!!!\n') 
    
    '''----------------------爬取说说----------------------'''
    try:
        get_shuoshuo(driver,file,username)
    except Exception as e:
        print(e)
        file.write('\n!!!!!说说抓取失败!!!!!\n')
    
    '''----------------------爬取日志---------------------'''
    try:
        timu(driver,file)
    except:
        file.write('\n!!!!!日志题目抓取失败!!!!!\n')  
    try:
        neirong(driver,file)
    except Exception as e:
        print(e)
        file.write('\n!!!!!日志内容抓取失败!!!!!\n')
    file.close()
    '''----------------------文件加密---------------------'''
    file0 = filename
    jiami_file = username+ "\\" + username+ '_encrypted'+'.csv'
    save_file(file0, jiami_file ,key)
    driver.quit()
    return True
    
    
    
if __name__ == '__main__':
    username = input('请输入QQ号:')
    password = input('请输入密码:')
    key = int(input('key:'))
    main(username,password,key)

3.encrypts0.py 进行文本加密

在这里插入图片描述
加密与解密原理:
使用ord()函数得道每个函数的编码值,将其与秘钥进行异或操作得到暗文
根据异或操作的性质,假设a是明文, k是秘钥, b是密文那么, a^k = b, b^k = a,只要加密和解密方的秘钥一致,就可以成功的加密解密。
例如,使用ord(‘我’) = 25105, 设置加密秘钥为123,那么25105123=25194,使用chr()函数可以得到编码值对应的字符,chr(25194)=‘扪’即为密文。解密时,如果秘钥为123,那么密文ord(’扪’)123 = 25194^ 123 = 25105, chr(25105)即为’我’,得到正确的明文。若秘钥不为123,则异或结果将得不到25105,因此解密之后得到的字符就会乱码了。

优点:
使用简单的异或操作即可实现,方法简单易实现、易理解,不需要导入额外的包,使用基本语法即可。解密即是加密的逆过程。
缺点:
由于异或操作即支持数值运算,因此秘钥只能为纯数字。

在这里插入图片描述

# -*- coding: utf-8 -*-
"""
Created on Mon Aug 10 20:29:37 2020

@author: Administrator
"""

import csv
import os

"""
原理:
   使用ord()函数得道每个函数的编码值,将其与秘钥进行异或操作得到暗文
   根据异或操作的性质,假设a是明文, k是秘钥, b是密文
   那么, a^k = b,  b^k = a
   只要加密和解密方的秘钥一致,就可以成功的加密解密
"""

def encode(l, key):
    """
    l:列表,即明文,l:列表,即明文,例如['aa','bb','cc']
    key: 秘钥(int型)
    返回:暗文(列表)
    """

        
    try:
        key = eval(key)
    except NameError:
        print("Invalid Key!Encrypt with default key.")
        key = 20
    else:
        if type(key)!= int:
            print("Invalid Key!Encrypt with default key.")
            key = 20
        elif key < 0 | key >= 1000:
            print("Invalid Key!Encrypt with default key.")
            key = 20
    
    
        

    encode_list = []
    for i in l:   # i 是一个字符串
        i = list(i)
        i = (chr(ord(j)^key) for j in i)   
        encode_list.append("".join(i))
    
    return encode_list


def save_file(file0, file1 ,key):


    f0 = open(file0, 'r', encoding='utf-8')
    f1 = open(file1, "w", encoding="utf-8", newline='')
    csv_reader = csv.reader(f0)
    csv_writer = csv.writer(f1)
    
    # reader与 writer都是以列表形式读出,并且可以以列表形式写入
    for cont in csv_reader:
        #print(cont)
        encode_row = encode(cont, key)
        csv_writer.writerow(encode_row)
        
        
    f0.close()
    os.remove(file0)
    f1.close()
    print("=======加密成功=======")
    
    
if __name__ == "__main__":
    save_file("说说.csv","说说_加密.csv", 123)

4.decrypts1.py 进行文本解密

    # -*- coding: utf-8 -*-
import csv
import random


def decode(l, key):
    """
    l:列表,即暗文,例如['aa','bb','cc']
    key: 秘钥(int型)
    返回:明文(列表)
    """
    try:
        key = eval(key)
    except NameError:
        print("Invalid Key!Decrypt with random key.")
        key = random.randint(0,100)
    else:
        if type(key)!= int:
            print("Invalid Key!Decrypt with random key.")
            key = random.randint(0,100)
        elif key < 0 | key >= 1000:
            print("Invalid Key!Decrypt with random key.")
            key = random.randint(0,100)

5.directory.py 创建用户目录

""""创建目录,为每一个登陆的qq创建一个目录,用来保存其提取到的信息"""
def mkdir(path):
    # 引入模块
    import os
 
    # 去除首位空格
    path=path.strip()
    # 去除尾部 \ 符号
    path=path.rstrip("\\")
 
    # 判断路径是否存在
    # 存在     True
    # 不存在   False
    isExists=os.path.exists(path)
 
    # 判断结果
    if not isExists:
        # 如果不存在则创建目录
        os.makedirs(path) 
 
        print(path+' 创建成功')
        return True
    else:
        # 如果目录存在则不创建,并提示目录已存在
        print(path+' 目录已存在')
        return False
 
# 定义要创建的目录
if __name__ == '__main__':
    mkpath="123123"
# 调用函数
    mkdir(mkpath)

6.shuoshuo_wzq.py 爬取说说

在这里插入图片描述
在这里插入图片描述

import time
from time import sleep
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from login import login1
import requests
import os

# 登录QQ空间
def get_shuoshuo(driver,f,username):
    driver.get('https://qzone.qq.com/')
    sleep(1)
    
    headers = {
        'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
        'Connection':'close',
        }
    requests.adapters.DEFAULT_RETRIES = 5
    s = requests.session()
    s.keep_alive = False
    path = username + '\\' + 'piclibs'
    if not os.path.exists(path):
        os.mkdir(path)
    print('----------------------------------------------')
    print('-----------------正在爬取说说------------------')
    #进入说说主界面
    driver.find_element_by_xpath('//*[@id="menuContainer"]/div/ul/li[5]/a').click()
    sleep(3)
    #创建新文件,记得要把之前生成的删掉
    f.write('\n==============说说==============\n')
    
    for j in range(2):
        driver.execute_script("window.scrollBy(0,20000)")
        time.sleep(1)
    
    num = 0
    while True:       
        #下拉页面,以便获取数据与点击翻页
        
        num += 1
        for j in range(2):
            driver.execute_script("window.scrollBy(0,20000)")
            time.sleep(1)
        #切换到读说说的架构当中
        iframe = driver.find_element_by_xpath('//*[@id="app_container"]/iframe')
        driver.switch_to.frame(iframe)  
        #进行读取
        content = driver.find_elements_by_css_selector('.content')
        for con in content:
            data = con.text
            #print(data)
            f.write(data+'\n')
            
        imgs = driver.find_elements_by_css_selector('a[title="查看大图"]')
        for i,img in enumerate(imgs):
            imgscr = img.get_attribute("href")
            img_data = requests.get(url = imgscr,headers = headers).content
            img_name = str(num) + 'page' + str(i) + '.jpg'
            img_path = path + '\\' + img_name
            
            #print(imgscr)
            with open(img_path,'wb') as fp:
                fp.write(img_data)
                
        #进行翻页,如果不能翻页则默认程序完成,说说爬取完毕
        try:
            driver.find_element_by_link_text(u'下一页').click()#点击下一页
            time.sleep(1)
            #该页说说爬取完毕后,要切换回默认值以便进行下拉页面
            driver.switch_to.default_content()
        except:
            print('-----------------说说爬取完成------------------')
            break

7.rizhi_neirong_wzq.py 爬取日志内容

在这里插入图片描述

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from time import sleep


def get_rizhi(driver,f):
    driver.get('https://qzone.qq.com/')
    sleep(1)
    
    print('----------------------------------------')
    print('----------正在爬取日志内容---------------')
    #进入说说主界面
    driver.find_element_by_xpath('//*[@id="menuContainer"]/div/ul/li[2]/a').click()
    sleep(3)
    

    try:
        #进入第一篇页面
        iframe = driver.find_element_by_xpath('//*[@id="tblog"]')
        driver.switch_to.frame(iframe)
        driver.find_element_by_xpath('//*[@id="listArea"]/ul/li[1]/div[1]/span/a').click()
        sleep(3)
        #创建新文件,记得要把之前生成的删掉
        f.write('\n=============日志内容=============\n')
        while True:       
            try:
                #切换frame到日志内容
                driver.switch_to.default_content()
                iframe = driver.find_element_by_css_selector('.app_canvas_frame')
                driver.switch_to.frame(iframe)  
                #爬取日志题目和内容
                title = driver.find_element_by_css_selector('.blog_tit_detail').text
                content = driver.find_element_by_css_selector('div[id = "blogDetailDiv"]').text
                #print(title+'\n'+content+'\n')
                f.write(title+'\n'+content+'\n\n')
                #进行翻页,没有下一页则执行except同时爬取结束
                pages = driver.find_element_by_css_selector('a[rel="nextBlog"]')
                driver.execute_script("arguments[0].click();", pages)
                sleep(3)
                
            except:
               
                print('----------日志内容爬取完成------------')
                break
    except:
        print('-----------------日志为空------------------')

8.rizhi_timu_wzq.py 爬取日志题目

在这里插入图片描述

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time
from time import sleep


# 登录QQ空间
def get_rizhi(driver,f):
    
    driver.get('https://qzone.qq.com/')
    sleep(1)
    print('---------------------------------------')
    print('----------正在爬取日志题目--------------')
    #进入日志主界面
    driver.find_element_by_xpath('//*[@id="menuContainer"]/div/ul/li[2]/a').click()
    sleep(3)
    #创建新文件,记得要把之前生成的删掉
    f.write('\n=============日志题目=============\n')
    while True:       
        #下拉页面,以便获取数据与点击翻页
        for j in range(2):
            driver.execute_script("window.scrollBy(0,5000)")
            time.sleep(2)
        #切换到读日志的架构当中
        iframe = driver.find_element_by_xpath('//*[@id="tblog"]')
        driver.switch_to.frame(iframe)  
        #进行读取
        content = driver.find_elements_by_css_selector('a[rel="blog-detail-link"]')
        for con in content:
            data = con.text
            #print(data)
            f.write(data+'\n')
        #进行翻页,如果不能翻页则默认程序完成,日志爬取完毕
        try:
            time.sleep(2)
            driver.find_element_by_link_text(u'下一页').click()#点击下一页
            time.sleep(2)
            #该页日志爬取完毕后,要切换回默认值以便进行下拉页面
            driver.switch_to.default_content()
        except:
            print('------------日志题目爬取完成--------------')
            break

9.information.py 爬取个人信息

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from login import login1 as login
from time import sleep


def get_information(driver,information_file,username):  
    sleep(1)
    driver.get('https://user.qzone.qq.com/'+username+'/1')
    sleep(2)
    driver.switch_to.frame('ttinfo')#
    sleep(1)
    biaoti = ['性别','年龄','生日','星座','现居地','婚姻状况','血型','故乡','职业','公司名称','公司所在地','详细地址']
    neirong = driver.find_elements_by_css_selector('.preview_option')
    
    information_file.write('\n=============个人信息==============\n')
    information = []
    for biao,nei in zip(biaoti,neirong):
        information.append((biao,nei.text))
        information_file.write(biao+':'+nei.text+'\n')

    return information

10.friends.py 爬取好友列表

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from login import login1 as login
from time import sleep


def friends_lis(driver,user,haoyou_file):
    sleep(1)
    #使用了url方法找到好友页面
    haoyou_url = 'https://user.qzone.qq.com/'+user+'/myhome/friends'
    driver.get(haoyou_url)
    #转换iframe
    iframe = driver.find_element_by_xpath('//iframe')
    sleep(2)	# 等待资源加载
    driver.switch_to.frame(iframe)
    sleep(1)
    #获取好友信息,转化为列表
    haoyou_file.write('\n=============好友列表=============\n')
    lis = (driver.find_element_by_xpath('//*[@id="mecarewho_list"]').text).split('\n')
    haoyou_lis = [lis[i] for i in range(1,len(lis),4)]
    for item in haoyou_lis:
        haoyou_file.write(item+'\n')
    before = haoyou_lis
    
    #存在多页情况#mecarewho_pager > a.qz-button.btn-pager-next
    while(True):
        try:
            next_page = driver.find_element_by_css_selector('#mecarewho_pager > a.qz-button.btn-pager-next')
            next_page.click()
            sleep(1)
            lis = (driver.find_element_by_xpath('//*[@id="mecarewho_list"]').text).split('\n')
            haoyou_lis = [lis[i] for i in range(1,len(lis),4)]
            if haoyou_lis == before:
                break
            else:
                before = haoyou_lis
            for item in haoyou_lis:
                haoyou_file.write(item+'\n')
        except:
            break
     
    sleep(1)

    return haoyou_lis

11.login.py 登录验证码识别

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from time import sleep
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


def login1(driver,username,password):
#    username = input('请输入QQ号:')
#    password = getpass.getpass('请输入密码:')
    driver.switch_to.frame('login_frame')
    sleep(3)
    driver.find_element_by_id('switcher_plogin').click()
    driver.find_element_by_id('u').clear()
    driver.find_element_by_id('u').send_keys(username)
    driver.find_element_by_id('p').clear()
    driver.find_element_by_id('p').send_keys(password)
    sleep(2)
    driver.find_element_by_xpath('//*[@id="login_button"]').click()
    sleep(2)
    
    try:#点击‘主页’,验证是不是登录成功
        driver.find_element_by_xpath('//*[@id="menuContainer"]/div/ul/li[1]/a').click()
        print('=========登录成功=========')
    except:#账号密码正确的前提下,未登录成功,说明有验证过程
        try:
            #需要转换frame
            iframe = driver.find_element_by_xpath('//iframe')
            sleep(2)	# 等待资源加载
            driver.switch_to.frame(iframe)
         
        	# 等待图片加载出来
            WebDriverWait(driver, 5, 0.5).until(
        		EC.presence_of_element_located((By.ID, "tcaptcha_drag_button"))
        	)
            button = driver.find_element_by_id('tcaptcha_drag_button')
            sleep(1)
            
            #按照偏移量循环调整滑块拖动距离
            bias = [0,10,-10,5,-5,3,-3,-1,1]
            for i in bias:
                action = ActionChains(driver)
                action.click_and_hold(button).perform()
                action.move_by_offset(xoffset=i+173, yoffset=0).perform()
                action.reset_actions()
                sleep(0.5)
                action.release().perform()
                sleep(5)
                try:#点击‘主页’,验证是不是登录成功
                    driver.find_element_by_xpath('//*[@id="menuContainer"]/div/ul/li[1]/a').click()
                    print('=========登录成功=========')
                    break
                except:
                    continue          
        except:
            print('=========账号或密码错误,请重新输入=======')
            username = None
            
    #print(username)
    return username
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值