zl程序教程

您现在的位置是:首页 >  后端

当前栏目

python爬虫实例——爬取微博热搜榜的评论

Python实例爬虫 评论 爬取
2023-09-27 14:20:17 时间

在这个实例中用到了手机模式下的动态网页爬取,实际上手机模式下的动态网页爬取一般比PC模式下的动态网页爬取简单些(因为手机模式下基本上都是动态网站,很少有伪动态网站)。

手机模式的操作:点击切换模式仿真(切换之后基本上就是手机模式了)——>点击网页刷新(如果看着不舒服可以点击刷新下面一栏的尺寸,选择自己喜欢的机型)——>向下滑直至翻页出现新的内容,剩下的跟之前讲的操作一样:python爬虫思路——动态网站

代码里cookie什么的用自己浏览器的,不会找的看这篇文章:python爬虫思路——静态网站

话就这么多,上代码:

import re
import time
import requests
import json


#获得热搜话题的标题
#这里用的是pc端的页面的headers
def get_title(hot_band_url):
    headers = {
         'user_agent' : '用自己浏览器的',
         'cookie':'用自己浏览器的',
         }

    data = requests.get(hot_band_url,headers=headers)  #请求

    data = json.loads(data.text)   #转字典格式
    title_list = []

    items = data['data'] if 'data' in data else {}  #找数据
    items = items['band_list'] if 'band_list' in items else {}   #找榜单列表
    for item in items:
        title = item['word'] if 'word' in item else None
        #如果找到标题,存入列表
        if title != None:
            title_list.append(title)

    return title_list


#获得所有热搜话题里的微博的id
# 这里用的是手机端的页面的headers
def get_id(title_list):   #
    headers = {
        'user_agent': '用自己浏览器的',
        'cookie': '用自己浏览器的',
    }
    id_list = []

    num = 0
    for title in title_list:
        time.sleep(3)  # 设置爬虫延时
        # 根据获取的标题进入该内容网页存放数据的文件
        url = 'https://m.weibo.cn/api/container/getIndex?containerid=231522type%3D1%26q%3D%23' + title + '%23'
        #这里只爬前几条微博里的id(第一页)
        try:  #程序保护,如果网页出现问题或别的报错跳过这次爬取
            data = requests.get(url, headers=headers)  # 请求数据
            data = json.loads(data.text)

            data = data['data'] if 'data' in data else {}  # 找数据
            items = data['cards'] if 'cards' in data else []  # 找存每条微博的列表

            num += 1
            print('爬了{}页的id'.format(num))
            # 接下来是一步步找id的过程,就像将洋葱一层层拨开
            for item in items:
                #第一种情况,在card_group的0里
                if 'card_group' in item:
                    id = item['card_group']  # 在item下找card_group
                    id = id[0] if id != [] else {}  # 在card_group下找0
                    id = id['mblog'] if 'mblog' in id else {}  # 在0下找mblog
                    id = id['id'] if 'id' in id else None  ##在mblog下找id

                    if id != None:
                        id_list.append(id)
                        '''保险起见存id'''
                        with open('id.txt', 'a', encoding='utf-8') as file:  # 在文件里续写
                            file.write(str(id) + '\n')
                #第二种情况,在card_group的1里
                elif 'card_group' in item:
                    id = item['card_group']  # 在item下找card_group
                    id = id[1] if id != [] else {}  # 在card_group下找0
                    id = id['mblog'] if 'mblog' in id else {}  # 在0下找mblog
                    id = id['id'] if 'id' in id else None  ##在mblog下找id

                    if id != None:
                        id_list.append(id)
                        '''保险起见存id'''
                        with open('id.txt', 'a', encoding='utf-8') as file:  # 在文件里续写
                            file.write(str(id) + '\n')
                #第三种情况,直接在mblog里
                elif 'mblog' in item:
                    id = item['mblog']  # 否则在item下找mblog
                    id = id['id'] if 'id' in id else None  ##在hot_page下找id

                    if id != None:
                        id_list.append(id)
                        '''保险起见存id'''
                        with open('id.txt', 'a', encoding='utf-8') as file:  # 在文件里续写
                            file.write(str(id) + '\n')
                #还有别的情况就不写了,毕竟是少数,干脆不要了

                else: pass
        except: continue
    file.close()

    return id_list


#获取所有id微博的评论
# 这里用的是手机端的页面的headers
def get_comments(id_list):
    headers = {
        'user_agent': '用自己浏览器的',
        'cookie': '用自己浏览器的',
    }

    num = 0  # 记录爬了多少次
    for id in id_list:  # 遍历每条微博
        max_id = 0
        while max_id != None:
            try:  
                time.sleep(5)  # 爬虫延时
                url = 'https://m.weibo.cn/comments/hotflow?mid=' + str(id) + '&max_id=' + str(max_id)
                txt = requests.get(url, headers=headers)
                jsn = json.loads(txt.text)

                data = jsn['data'] if 'data' in jsn else {}  # 获取数据
                items = data['data'] if 'data' in data else {}  # 得到存数据的列表
                max_id = data['max_id'] if 'max_id' in data else None  # 得到max_id

                # 判断是否爬取完,因为最后一次爬的评论的max_id=0,判断循环结束的条件是max_id=None,所以改一下
                if max_id == 0:
                    max_id = None

                with open('pl.txt', 'a', encoding='utf-8') as file:  # 在文件里续写
                    for item in items:  # 遍历列表每个评论
                        texts = item['text'] if 'text' in item else None  # 找到评论文本
                        texts = re.sub('\<.*\>', ' ', texts)  # 去除一些标签转译成的符号
                        file.write(texts + '\n')
                        num += 1
                        if num % 10 == 0:
                            print('爬了{}条评论'.format(num))
            except: max_id = None

    file.close()


if __name__ == '__main__':
    hot_band_url = 'https://weibo.com/ajax/statuses/hot_band'
    title_list = get_title(hot_band_url=hot_band_url)
    id_list = get_id(title_list=title_list)
    #id_list = []
    #with open('id.txt', 'r') as file:
    #    for line in file.readlines():
    #        line = line.replace('\n', '')
    #        id_list.append(line)
    get_comments(id_list)