从零开始爬QQ空间

该博客介绍用Python爬取QQ空间数据,包括说说内容、发表时间等。详细说明了运行代码的必要准备,如安装selenium、bs4、pandas包等,还给出主要代码流程,如登录、获取数据等。同时指出代码存在假死、数据缺陷等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

爬取QQ空间数据(包括说说内容、发表时间、评论数、发布者手机标识)。很很很很很容易上手!

必要准备

作为一个有追求的爬虫,该代码运行需要以下准备:

  1. selenium包 ,在cmd内输入 ‘pip install Selenium’ ;
  2. bs4包,输入 ‘pip install bs4’ ;
  3. pandas包,‘pip install pandas’;
  4. chrome浏览器 ,下载见 https://www.google.cn/intl/zh-CN/chrome/ 或者其他;
  5. 对应版本的chromedriver,下载见http://chromedriver.storage.googleapis.com/index.html ,版本对应见 https://blog.youkuaiyun.com/weixin_42730631/article/details/87607958#ChromeDriverChrome_1 下载后放在代码所在目录下;

初始化

friend = '2470288667'  # 朋友的QQ号,朋友的空间要求允许你能访问,这里可以输入自己的qq号
user = ''  # 你的QQ号
pw = ''  # 你的QQ密码
global start_num,goal_num,next_num
start_num = 1 # 设置开始爬取的页码,从头开始则设为0
goal_num = 2000 # 设置爬取的页数 
next_num = 1  # 初始“下一页”的id

主要代码

登录

def login():    #登录并跳转至空间说说页面
    global driver
    driver = webdriver.Chrome()    # 获取浏览器驱动
    driver.maximize_window()    # 浏览器窗口最大化
    driver.get("http://i.qq.com")    # 浏览器地址定向为qq登陆页面
    driver.switch_to.frame("login_frame")    # 定位到登录所在的frame
    driver.find_element_by_id("switcher_plogin").click()    # 自动点击账号登陆方式
    driver.find_element_by_id("u").send_keys(user)    # 账号输入框输入已知qq账号
    driver.find_element_by_id("p").send_keys(pw)    # 密码框输入已知密码
    driver.find_element_by_id("login_button").click()    # 自动点击登陆按钮
    time.sleep(1)    # 让webdriver操纵当前页
    driver.switch_to.default_content()
    driver.get("http://user.qzone.qq.com/" + friend + "/311")    # 跳到说说的url, friend可以任意改成想访问的空间
    try:
           button = driver.find_element_by_id("dialog_button_1").click()    # 找到关闭按钮,关闭提示框
    except:
        pass

跳转初始页

def switch_to_startpage():  # 跳转到start_num后开始爬取
    global driver
    global start_num
    for i in range(0, 5):
        height = 25000 * i
        strWord = "window.scrollBy(0," + str(height) + ")"
        driver.execute_script(strWord)
        time.sleep(2)
    driver.switch_to.frame("app_canvas_frame")
    driver.find_element_by_id("pager_go_0").send_keys(str(start_num))
    driver.find_element_by_id('pager_gobtn_0').click()
    driver.switch_to.parent_frame()

获取数据

def get_data():    # 获取数据 
    global driver,next_num,goal_num
    driver.set_page_load_timeout(60)
    driver.set_script_timeout(60)
    for i in range(0, 5):    # 下拉滚动条,使浏览器加载出全部的内容,
        height = 25000 * i  # 每次滑动25000像素,分5次完成
        strWord = "window.scrollBy(0," + str(height) + ")"
        driver.execute_script(strWord)
        time.sleep(2)
        to_content_txt()
        to_analysis_csv()
        if driver.page_source.find('pager_next_' + str(next_num)) == -1:   # 当已经到了尾页,“下一页”这个按钮就没有id了,可以结束了
            break       
        if next_num == goal_num:    # 爬取足够的页数则跳出循环  
            break       
        driver.find_element_by_id('pager_next_' + str(next_num)).click()    # 找到“下一页”的按钮,因为下一页的按钮是动态变化的,这里需要动态记录一下      
        next_num += 1    # “下一页”的id    
        driver.switch_to.parent_frame()    # 因为在下一个循环里首先还要把页面下拉,所以要跳到外层的frame上

解析数据

def to_content_txt():    # 源码写入txt
    global driver,content
    driver.switch_to.parent_frame()    # 因为在下一个循环里首先还要把页面下拉,所以要跳到外层的 frame上      
    driver.switch_to.frame("app_canvas_frame")    # 这里需要选中说说所在的frame,否则找不到下面需要的网页元素
    content = BeautifulSoup(driver.page_source, "html5lib")    # 解析页面元素
    with open('content.txt','a',encoding='utf-8') as c:    # 写入content
        c.write(content.prettify())
        
def to_analysis_csv():    # 所需数据写入csv
    global content
    l_ss_contents,l_times,l_phones,l_com = [],[],[],[]
    
    ss = content.find_all('pre')    # 说说内容
    for i in range(len(ss)):
        ss1 = ss[i]
        try:
            l_ss_contents.append(ss1.contents[0])
        except:
            l_ss_contents.append('img')    # 若有图片,则写入为 img
    
    infos = content.find_all('div','info')    # 手机型号、发布时间    
    for i in range(len(infos)):
        info1 = infos[i]
        time1 = info1.a.attrs['title']    
        l_times.append(time1)  
        phone = info1.find_all('span')[-1].contents[0]
        l_phones.append(phone)
    
    comments = content.find_all('div','op')    # 评论数
    for i in range(len(comments)):
        comments[i] = comments[i].find('a',"c_tx comment_btn")
    i=0    
    while True:
        while i in range(0,len(comments)):
            try:    # 排除评论数的干扰项
                comment = comments[i].contents[0]
            except:
                i+=1
                break            
            l_num = []
            for j in list(comment):    # 提取字符串中的数字并转为int
                if j.isdigit():
                    l_num.append(j)
            comment = ''.join(l_num)
            if comment != '':
                comment = int(comment)
            else:
                comment = 0
            l_com.append(comment)
            i += 1    
        if i > len(comments)-1:
            break

    d = {'d_comments':l_com,'d_phones':l_phones,'d_ss_contents':l_ss_contents,'d_times':l_times}    # 转为字典
    try:    # 转成dataframe并写入csv
        ss_df = pd.DataFrame(d)
        ss_df.to_csv('analysis.csv',mode = 'a',encoding = 'utf-8-sig')
    except:     # 排除因转发使series不等长
        pass

运行

if __name__ == '__main__':
    login()
    switch_to_startpage()
    try:
        while True:
            get_data() 
    except:
        print(next_num+start_num)    # 输出停止页面数

作者的话

  1. 这是小组课程作业,G同学做了很大贡献。
  2. 爬取部分有参考许多代码,感谢各路大神。(其实很容易看出来写得很乱的那一坨代码是我干的)
  3. 该代码有缺陷,如假死数据缺陷。 前者指爬取400~500页数据时可能假死。后者指:1. 如果有转发内容会跳过当前整页数据;2.beautifulsoup 解析时无法识别图片与表情,会影响说说文本内容。
  4. 此作业是为ddl所逼,尚不完善,欢迎批评指正
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值