目标网站
找合适的微博地址(一级和二级评论):https://weibo.com/5039775130/QcD89eXtz

获取cookie:

评论链接分析
一级评论
按热度排序

观察第一页链接的预览,max_id为红框中下一页的链接参数
按时间排序

二级评论
多页结构和一级评论类似

总结:(QcD89eXtz等价转换5230103573565221(mid),为微博帖子的mid,uid是可以随便写的目测不影响,每一页加载完的预览max_id提供了下一页的链接参数,flow:0热度排序,1时间排序。fetch_level、is_mix:0评论,1评论回复)
https://weibo.com/ajax/statuses/buildComments?is_reload=1&id=5230103573565221&is_show_bulletin=2&is_mix=0&count=10&uid=5039775130&fetch_level=0&locale=zh-CN
https://weibo.com/ajax/statuses/buildComments?is_reload=1&id={weibo_id}&is_show_bulletin=2&is_mix=0&count=20&page=
评论格式分析

data 0:
dr = re.compile(r'<[^>]+>', re.S) # 用正则表达式清洗评论数据
text2 = dr.sub('', data['text'])
text_list.append(text2) # 评论内容
time_list.append(trans_time(v_str=data['created_at'])) # 评论时间
like_count_list.append(data['like_count']) # 评论点赞数
source_list.append(data['source']) # 评论者IP归属地
user_name_list.append(data['user']['screen_name']) # 评论者姓名
user_id_list.append(data['user']['id']) # 评论者id
user_gender_list.append(tran_gender(data['user']['gender'])) # 评论者性别
follow_count_list.append(data['user']['follow_count']) # 评论者关注数
followers_count_list.append(data['user']['followers_count']) # 评论者粉丝数
转发评论同理
base_url = "https://weibo.com/ajax/statuses/repostTimeline"
params = {
"id": mid,
"page": str(page),
"moduleID": "feed",
"count": "20"
}
注:page控制一级评论翻页也行。
import requests
import csv
import time
# https://weibo.com/2644975784/5229613988188573#repost
# https://weibo.com/5039775130/QcD89eXtz
# 配置参数
weibo_id = "QcD89eXt" # 替换为目标微博的ID(从网页URL中可获得)
cookie = "XSRF-TOKEN=XU8_AFjrLY5a4AAqjbR1FwxN; SCF=Aup057BA3pnLYH3D_0o6kVlBMaUmbvrxluPNRHktBUa77nl6_SIicN7p16uYwSrHtJ79tT6XLB3s5X3ITsL4DNw.; SUB=_2A25EC1O-DeRhGeFG7lEV8yzIyjmIHXVnael2rDV8PUNbmtANLUrWkW9NeUX04Hh4MYjuKPIb-ySjLlZXoMyduuFY; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WFGK.uvaVIOqmnF7.QfyYUY5JpX5KzhUgL.FoMRSKeXe0zXeK-2dJLoIEBLxKnL12zL12qLxKqLBozLBoeLxKnL1K.L12-LxKqLB.2L1K5t; ALF=02_1765191918; WBPSESS=KfgmRchBqZijkVmYGCR-4izA5O32g3S-h3KzCpbmoPeG6aNxzukxIVcw2PmOTRAULZYtUSHame9bxDKBv1IAhTPzSDdHa2R1FhyAUXqKfbfuerxt6Vwz8gxmwnAR8m-pscvUnl_t9RsX58u2cn8ABA==" # 替换为浏览器登录后的Cookie,用于身份验证
# 请求头,包含用户代理、Cookie 和 Referer(来源页面)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Cookie": cookie,
"Referer": f"https://weibo.com/2803301701/{weibo_id}" # 2803301701 为人民日报微博的UID
}
# 定义获取微博一级评论的函数
def get_comments(weibo_id, max_page=5):
comments = [] # 存储评论内容
# 构造评论接口的URL模板,每页包含20条评论
url_template = f"https://weibo.com/ajax/statuses/buildComments?flow=0&is_reload=1&id={weibo_id}&is_show_bulletin=2&is_mix=0&count=20&page=" # 按热度排序下载一级评论
# 遍历页数,逐页爬取
for page in range(1, max_page + 1):
try:
# 发送 GET 请求获取当前页的评论数据
response = requests.get(url_template + str(page), headers=headers)
data = response.json() # 将响应内容解析为 JSON 格式
# 如果没有数据字段,说明已无更多评论,提前结束
if not data.get("data"):
print(f"第 {page} 页无数据,可能已爬完所有评论")
break
# 遍历每条评论,提取原始文本并清洗(去除换行符)
for comment in data["data"]:
text = comment["text_raw"].strip().replace("\n", " ")
comments.append([text]) # 加入列表,格式为嵌套列表以便写入CSV
print(f"已爬取第 {page} 页,当前总计 {len(comments)} 条评论")
time.sleep(2) # 每次请求后暂停2秒,防止触发反爬机制
except Exception as e:
print(f"第 {page} 页出错: {e}")
break # 若出错(如网络异常或请求被拒),提前终止爬取
return comments # 返回所有爬取到的评论列表
# 执行评论爬取
comments = get_comments(weibo_id)
# 将评论保存为 CSV 文件
with open("weibo_comments.csv", "w", encoding="utf-8-sig", newline="") as f:
writer = csv.writer(f)
writer.writerow(["评论内容"]) # 写入表头
writer.writerows(comments) # 写入评论内容
print(f"爬取完成!共 {len(comments)} 条评论已保存到 weibo_comments.csv")
参考
使用Python进行新浪微博的mid和url互相转换实例(10进制和62进制互算) / 张生荣
python爬虫爬取微博评论--完整版(超详细,大学生不骗大学生)_python爬取网页评论-CSDN博客
Python爬虫—爬取微博评论数据_微博评论爬取-CSDN博客
https://mp.weixin.qq.com/s/8ccbzjIUA7xf3yzKTlVIyQ
多级评论参考 代码
# https://mp.weixin.qq.com/s/iVy-oo25xlawkI-XS6JtUg
# https://m.weibo.cn/detail/4813628149072458
import requests
import re
import sys
import pymysql
import time
import random
from jsonpath import jsonpath
class WeiBo():
def __init__(self):
# 一级评论的接口信息
self.first_url = 'https://m.weibo.cn/comments/hotflow'
self.first_data = {
'id': '4813628149072458',
'mid': '4813628149072458',
'max_id': None,
'max_id_type': '0'
}
# 二级评论的接口信息
self.second_url = 'https://m.weibo.cn/comments/hotFlowChild'
self.second_data = {
'cid': '4813643344774141',
'max_id': '0',
'max_id_type': '0'
}
self.headers = {
'referer': 'https://m.weibo.cn/detail/4813628149072458',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1',
'cookie': '你的cookie'
}
# 数据库
self.db = pymysql.connect(
host='localhost', # 连接数据库
user='数据库账号',
passwd='数据库密码',
database='数据库名'
)
self.cursor = self.db.cursor()
# 获取一级评论
def get_first_data(self):
self.first_response = requests.get(self.first_url, params=self.first_data, headers=self.headers)
self.first_data_json = self.first_response.json() # json数据类型
# 根据网页数据包结构,获取以及评论的内容以及评论者
self.first_names = jsonpath(self.first_data_json, '$..data[:].user.screen_name')
self.first_textss = jsonpath(self.first_data_json, '$..data[:].text')
# 3.2 获取一级评论的cid,以匹配二级评论。放入for循环中遍历
self.cids = jsonpath(self.first_data_json, '$..data[:].rootid')
# 1.1获取网页max_id作为下一页的翻页参数
self.max_id = jsonpath(self.first_data_json, '$..data.max_id')
for self.first_name, self.first_texts, self.cid in zip(self.first_names, self.first_textss, self.cids):
print('=========一级评论=========') # 分隔符
self.first_text = re.sub('<.*?>', '', self.first_texts) # 正则处理表情包
print(self.first_name, '----->', self.first_text)
# 3.3 将循环遍历得到的cid改写二级评论初始化字典值
self.second_data['cid'] = self.cid
# 3.1 调用二级评论方法
time.sleep(random.uniform(5, 9))
try: # 异常处理:如果没有二级评论还调用二级方法,json()解析不到数据就会报错:requests.exceptions.JSONDecodeError
self.get_second_data()
except:
print('\t\t\t\t=========没有二级评论=========')
# 1.2 要等第一页爬完之后才能递归调用
self.first_data['max_id'] = self.max_id
# 2.5 根据2.4添加条件判断
if self.first_data['max_id'] == 0:
print('一级评论获取完毕')
else:
# 1.3 递归调用,递归肯定会有程序报错的时候,所以我们要异常处理
time.sleep(random.uniform(6, 9))
self.get_first_data()
# 获取二级评论
def get_second_data(self):
second_response = requests.get(self.second_url, params=self.second_data, headers=self.headers)
self.second_data_json = second_response.json() # json数据类型
self.second_names = jsonpath(self.second_data_json, '$..data[:].user.screen_name')
self.second_textss = jsonpath(self.second_data_json, '$..data[:].text')
# 2.1获取二级网页max_id作为下一页的翻页参数
self.second_max_id = jsonpath(self.second_data_json, '$..max_id')[0]
# print(self.second_max_id)
# print('\t\t\t\t', '-----------二级评论-----------') # 分隔符
for self.second_name, self.second_texts in zip(self.second_names, self.second_textss):
self.second_text = re.sub('<.*?>', '', self.second_texts) # 正则处理表情包
print('\t\t\t\t', self.second_name, '----->', self.second_text)
# 4 保存
self.save_data()
# 2.2递归调用
self.second_data['max_id'] = self.second_max_id
# 2.4 max_id=0时翻页结束,不等于0才递归
if self.second_data['max_id'] == (0 | 186494897570): # 第一条评论的最后一条跟评的数据报的max_id不知道怎么会使变了,所以只能加进来,否则程序报错
print('------------二级评论获取完毕------------')
self.second_data['max_id'] = 0
else:
time.sleep(random.uniform(7, 11))
self.get_second_data()
# 保存方法
def save_data(self):
sql = "insert into weibo_comments(first_author, first_comment, second_author, second_comment) values(%s, %s, %s, %s)" # 占位符
data = [self.first_name, self.first_text, self.second_name, self.second_text] # 使用占位符插入数据,之前所有的代码前加self就是为了方便在类中共用变量,方便保存
self.cursor.execute(sql, data) # data要tuple、list、dict类型
self.db.commit()
def main(self):
self.get_first_data()
# self.get_second_data()
if __name__ == '__main__':
weibo = WeiBo()
weibo.main()
搜索:https://mp.weixin.qq.com/s/PPl8Ij229Qnb-WU4K3BWkw、https://mp.weixin.qq.com/s/UzDBZzaLZox67y0ge2Y2tg、https://mp.weixin.qq.com/s/mMiVehzTsW-rTNbPGRnoqw



2万+

被折叠的 条评论
为什么被折叠?



