使用Python爬取QQ群成员信息

狡猾的骗骗花
• 阅读 2065

直接贴代码

import os
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import json
import csv
import re

qq = ''
if qq == '':
    qq = str(int(time.time()))
# 初始化一些东西
option = webdriver.ChromeOptions()
option.binary_location = r'C:\Program Files\Google\Chrome\Application\chrome.exe'
cmd_path = os.path.join(os.getcwd())
save_path = os.path.join(os.getcwd(), 'data', qq)
if not os.path.exists(save_path):
    os.mkdir(save_path)

def test():
    # 构建谷歌驱动器
    # browser = webdriver.Chrome(r'C:\Tools\chromedriver.exe', options=option)
    # browser.get("https://www.baidu.com/")
    return True


# 开始登陆
def login_spider():
    url = 'https://qun.qq.com/'
    # 构建谷歌驱动器
    browser = webdriver.Chrome(r'C:\Tools\chromedriver.exe', options=option)
    # 请求url
    browser.get(url)
    # 模拟登陆,首先找到登陆的id,并点击
    browser.find_element_by_css_selector('#headerInfo p a').click()
    # 点击之后会弹出一个登陆框,这时候我们用显示等待来等待这个登陆框加载出来
    WebDriverWait(browser, 1000).until(
        EC.presence_of_all_elements_located(
            (By.CSS_SELECTOR, '#loginWin iframe')
        )
    )
    print('登陆框已加载')
    # 登陆框加载之后,我们发现整个登陆框其实就是另一个网网页
    # 如果在原网页操作这个登陆框的话,是不能操作的
    # 所以我们只需要提取iframe标签的src属性,然后再去访问这个url即可实现
    # 自动登陆
    # 找到iframe标签并获取是如此熟悉
    iframe_url = browser.find_element_by_css_selector('#loginWin iframe').get_attribute('src')
    # 再访问这个url
    browser.get(iframe_url)
    # 找到快捷登陆的头像并点击
    # 首先用显示等待这个头像已经加载完成
    WebDriverWait(browser, 1000).until(
        EC.presence_of_all_elements_located(
            (By.ID, 'qlogin_list')
        )
    )
    browser.find_element_by_css_selector('#qlogin_list a').click()
    print('登陆成功')
    return browser


# 切换句柄操作
def switch_spider(browser):
    # 登陆成功之后,我们就找到群管理的标签并点击,首先等待这个元素加载完成
    WebDriverWait(browser, 1000).until(
        EC.presence_of_all_elements_located(
            (By.XPATH, './/ul[@id="headerNav"]/li[3]')
        )
    )
    browser.find_element_by_xpath('.//ul[@id="headerNav"]/li[3]').click()
    # 点击之后,我们找到成员管理标签并点击
    WebDriverWait(browser, 1000).until(
        EC.presence_of_all_elements_located(
            (By.CLASS_NAME, 'body')
        )
    )
    browser.find_element_by_xpath('.//div[@class="body"]/ul[1]/li[1]').click()
    # 打印全部窗口句柄
    # print(browser.window_handles)
    # 打印当前窗口句柄
    print(browser.current_window_handle)
    # 注意这里点击成员管理之后会自动跳转到一个新窗口打开这个页面
    # 所以我们需要将窗口句柄切换到这个新窗口
    browser.switch_to.window(browser.window_handles[1])
    # 解释一下browser.switch_to.window是获取当前一共有几个窗口
    # 这里是2个
    # browser.switch_to.window这个是指定当前游标切换到哪个窗口
    # 其实也可以这么写
    # all_window = browser.switch_to.window返回的是一个列表
    # browser.switch_to.window(all_window[1])
    # 效果是一样的
    return browser


# 开始采集数据
def start_spider(browser):
    # 声明一个列表存储字典
    data_list = []
    # 切换句柄之后,我们显示等待窗口出来
    WebDriverWait(browser, 1000).until(
        EC.presence_of_all_elements_located(
            (By.CLASS_NAME, 'my-all-group')
        )
    )

    # 筛选出我加入的群标签
    lis = browser.find_elements_by_xpath('.//div[@class="my-all-group"]/ul[2]/li')
    if len(lis) == 0:
        # 如果自己没有创建群,我加入的群就会跑到上面去
        lis = browser.find_elements_by_xpath('.//div[@class="my-all-group"]/ul[1]/li')

    # 遍历
    num = 0
    while True:
        try:
            # 按顺序选择群并获取信息
            # 先点击该群获取成员信息
            if lis is None:
                break
            if len(lis) == 0:
                break
            try:
                lis[num].click()
            except BaseException as e:
                print("读取完毕")
                break
            # 显示等待信息加载完成
            WebDriverWait(browser, 1000).until(
                EC.presence_of_all_elements_located(
                    (By.CLASS_NAME, 'list')
                )
            )
            # 获取该群当前有多少人,后面翻页需要
            groupMemberNum = eval(browser.find_element_by_id('groupMemberNum').text)
            # 获取群名称和群号码
            groupTit = browser.find_element_by_id('groupTit').text

            # 每一次翻页都会刷新21条信息,所以写个循环
            # 这里加1是因为假如一个群有36人,那么count=1,如果循环的话就不会翻页了
            # 也就是只能抓到一页的数据,大家可以自己想想其中的流程就知道了
            count = groupMemberNum // 21 + 1
            # 这里我只爬取每个群的一部分,如果想爬取全部成员信息
            # 请注释下面的if语句
            # if count > 5:
            #     count = 5
            # 每次循环都进行翻页
            while count:
                count -= 1
                browser.execute_script('document.documentElement.scrollTop=100000')
                time.sleep(2)
            time.sleep(3)
            # 开始获取成员信息
            trs = browser.find_elements_by_class_name('mb')
            # 创建一个组存储成员信息
            qun_numbers_list = []
            if trs:
                # 遍历
                for tr in trs:
                    tds = tr.find_elements_by_tag_name('td')[2:]
                    if len(tds) == 8:
                        # qq网名
                        qq_name = tds[0].text
                        # 群名称
                        group_name = tds[1].text
                        # qq号
                        qq_number = tds[2].text
                        # 性别
                        gender = tds[3].text
                        # qq年龄
                        qq_year = tds[4].text
                        # 入群时间
                        join_time = tds[5].text
                        # 等级(积分)
                        level = None
                        # 最后发言时间
                        end_time = tds[6].text

                        # 声明一个字典存储数据
                        data_dict = {'qq_name': qq_name, 'group_name': group_name, 'qq_number': qq_number,
                                     'gender': gender, 'qq_year': qq_year, 'join_time': join_time, 'level': level,
                                     'end_time': end_time}
                        qun_numbers_list.append(data_dict)
                        print(data_dict)
                    elif len(tds) == 9:
                        # qq网名
                        qq_name = tds[0].text
                        # 群名称
                        group_name = tds[1].text
                        # qq号
                        qq_number = tds[2].text
                        # 性别
                        gender = tds[3].text
                        # qq年龄
                        qq_year = tds[4].text
                        # 入群时间
                        join_time = tds[5].text
                        # 等级(积分)
                        level = tds[6].text
                        # 最后发言时间
                        end_time = tds[7].text

                        # 声明一个字典存储数据
                        data_dict = {'qq_name': qq_name, 'group_name': group_name, 'qq_number': qq_number,
                                     'gender': gender, 'qq_year': qq_year, 'join_time': join_time, 'level': level,
                                     'end_time': end_time}
                        # data_list.append(data_dict)
                        qun_numbers_list.append(data_dict)
                        print(data_dict)

            browser.find_element_by_id('changeGroup').click()
            time.sleep(3)
            WebDriverWait(browser, 1000).until(
                EC.presence_of_all_elements_located(
                    (By.CLASS_NAME, 'ui-dialog')
                )
            )
            lis = browser.find_elements_by_xpath('.//div[@class="my-all-group"]/ul[2]/li')
            if len(lis) == 0:
                # 如果自己没有创建群,我加入的群就会跑到上面去
                lis = browser.find_elements_by_xpath('.//div[@class="my-all-group"]/ul[1]/li')
            # 将群成员数据写入json文件
            p = list(re.findall(r'(.*)\((.*)\)$', groupTit)[0])
            g_name = p[0]
            gid = p[1]
            file_save_path = os.path.join(save_path, str(gid) + ".json")
            with open(file_save_path, 'a+', encoding='utf-8') as f:
                json.dump({"name": g_name, 'gid': gid, "numbers": qun_numbers_list}, f)
            num += 1
        except Exception as e:
            print("发生异常", e)
            raise Exception(e)

    return data_list


def main():
    print("======开始抓取======")
    browser = login_spider()
    browser = switch_spider(browser)
    start_spider(browser)
    print("======抓取完毕======")

if __name__ == '__main__':
    if test():
        main()
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
4cast
4castpackageloadcsv.KumarAwanish发布:2020122117:43:04.501348作者:KumarAwanish作者邮箱:awanish00@gmail.com首页:
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
狡猾的骗骗花
狡猾的骗骗花
Lv1
男 · 小太阳幼稚园 · 学生
_(:з」∠)_ 我好惨啊
文章
5
粉丝
2
获赞
7