本人为文科生尝试编程,学过一点点c++编程;两个月前结合b站的教程+询问朋友后成功运行了代码爬取微博评论,但现在发现出现如下报错,多次尝试检索均未找到相应解决方案,恳请解答
源码如下:
```python
import requests # 用于发送HTTP请求,从微博API获取数据
import csv # 用于处理CSV文件,将爬取的数据保存到CSV文件中
import time # 提供时间相关的函数,用于控制爬取速度(防止频繁请求导致被封禁)
import json # 用于解析和处理JSON格式的数据
import random # 提供随机数生成,用于随机延迟(避免频繁请求)
import traceback # 用于捕获和打印异常的详细信息,便于调试
# 创建文件对象
f = open(file='weibo_comments.csv', mode='w', encoding='utf-8-sig',
newline='') # 打开一个CSV文件,命名为weibo_comments.csv,写模式('w')
# 字典写入方法,创建一个字典写入器对象,用于将字典数据写入CSV文件
csv_writer = csv.DictWriter(f, fieldnames=[
'昵称',
'性别',
'地区',
'内容',
'发布时间',
'点赞数'
])
# 写入CSV文件的表头
csv_writer.writeheader()
# 获取评论内容的函数
def GetContent(MaxId, weibo_id, uid):
"""获取评论内容的函数"""
# 定义了HTTP请求头,包括User-Agent和Cookie,用于模拟浏览器请求
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36',
'Cookie': 'SCF=AlMxd4JS8fo0sHA-lS2L2Pil0uCPzZELfNDm60V-pAy_0E5ji0gvDfAl4QifQK6xYBIWFYdM4t5JApPxaTNxYZ4.; XSRF-TOKEN=Pgyv_jTAjubmbE_oYn9Iu8dd; WBPSESS=b6QVOSx6TcL3FVXi5xI1idMCrRV73gDdQNeUOXRi3pt_AnW5lxsUhTe7VdO2bQlJcAmv8bpvzCu0pw3_o-e9wkFsiTe60oMhbeieXwp8gD_RB4bDfZTP1e2lxrbGvqKdRpViiSqe0Gqb2J54HWqUAA==; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9Wh_dOzR2bIgoMoyf7pjwfNs5JpX5K-hUgL.FoMEehnEeoqEeoB2dJLoIp7LxKML1KBLBKnLxKqL1hnLBoMNeo5ReozceozX; ALF=1742103657; SUB=_2A25Kqqc5DeRhGeFM61oT8ijOyTiIHXVpyabxrDV8PUJbkNANLWbQkW1NQPhxSzM4WtV2j3cqkmWzeQyRNp28I1Vz'
}
url = 'https://weibo.com/ajax/statuses/buildComments' # 微博评论API的地址
# 传递给API的参数,包括微博ID、用户ID和分页参数
data = {
'flow': '0',
'is_reload': '1',
'id': weibo_id, # 此条微博的id
'is_show_bulletin': '2',
'is_mix': '0',
'max_id': MaxId, # 用于翻页的一个参数
'count': '20',
'uid': uid, # 用户的id
'fetch_level': '0'
}
# try后是正常的处理逻辑,except Exception as e:捕获所有异常,确保程序不会因错误而崩溃
try:
response = requests.get(url=url, params=data, headers=headers) # 发送HTTP GET请求,获取评论数据
json_data = response.json() # 解析API返回的JSON数据
# 添加数据检查和调试信息
print(f"API返回状态: {response.status_code}")
print(f"返回数据条数: {len(json_data.get('data', []))}")
if 'data' not in json_data or not json_data['data']:
print(f"当前页面没有数据,返回内容: {json_data}")
return 0, True
data_list = json_data['data'] # 提取评论列表
if len(data_list) == 0:
print("评论列表为空,已到达最后一页")
return 0, True
# 记录总评论数
total_number = json_data.get('total_number', 0)
current_count = len(data_list) # 当前页评论数
print(f"微博总评论数: {total_number}")
# for循环遍历评论列表,提取列表里面元素内容
for index in data_list:
name = index['user']['screen_name'] # 昵称
city = index['user']['location'] # 地区
text = index['text_raw'] # 评论原文(不含表情符号的HTML)
gender = index['user']['gender'] # f->女 m->男
created_at = index['created_at'] # 发布时间
like_counts = index['like_counts'] # 点赞数
# 根据性别标识符(f或m)将性别转换为中文(女/男)
if gender == 'f':
sex = '女'
elif gender == 'm':
sex = '男'
else:
sex = '保密'
# 保存到字典中
dit = {
'昵称': name,
'性别': sex,
'地区': city,
'内容': text,
'发布时间': created_at,
'点赞数': like_counts
}
# 写入数据
csv_writer.writerow(dit) # 将提取的评论数据写入CSV文件
print(f"已写入: {name} 的评论")
max_id = json_data.get('max_id', 0) # 获取下一页评论的标识符,用于分页加载评论
is_end = (max_id == 0 or len(data_list) == 0) # 判断是否已经加载完所有评论。在下一页的标识符为'0'或当前页评论列表已经为空时,结束爬取
# 如果已经获取的评论数达到总评论数,结束爬取,基于微博的总评论数(total_number),能够确保在极端情况下(例如 API 分页逻辑异常或数据丢失)仍然能够停止爬取,避免无限循环。
if current_count >= total_number:
is_end = True
return max_id, is_end
# 将捕获的异常实例赋值给变量 e,方便后续处理和调试
except Exception as e:
print(f"获取评论出错: {e}")
print(f"原始响应: {response.text[:200]}") # 如果HTTP请求失败或返回的响应不符合预期,这段代码会打印响应内容的前 200 个字符。
return 0, True # 如果发生异常,程序不会继续执行后续逻辑,而是直接返回两个值
# 从输入的微博链接中提取所需参数的函数
def extract_weibo_ids(url):
"""从微博链接中提取微博ID和用户ID"""
try:
# 处理标准微博链接格式:https://weibo.com/1683472727/Of9fGd3dz
parts = url.strip('@').split('/') # strip('@')去除URL中多余的@符号;split('/')表示 将URL按照/分割成一个列表
uid = parts[-2] # 用户ID,表示取列表中倒数第二个元素,对应用户ID
mid = parts[-1] # 微博ID (Of9fGd3dz 格式),对应倒数第一个元素
# 将mid转换为数字格式的weibo_id
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': 'SCF=AlMxd4JS8fo0sHA-lS2L2Pil0uCPzZELfNDm60V-pAy_0E5ji0gvDfAl4QifQK6xYBIWFYdM4t5JApPxaTNxYZ4.; XSRF-TOKEN=Pgyv_jTAjubmbE_oYn9Iu8dd; WBPSESS=b6QVOSx6TcL3FVXi5xI1idMCrRV73gDdQNeUOXRi3pt_AnW5lxsUhTe7VdO2bQlJcAmv8bpvzCu0pw3_o-e9wkFsiTe60oMhbeieXwp8gD_RB4bDfZTP1e2lxrbGvqKdRpViiSqe0Gqb2J54HWqUAA==; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9Wh_dOzR2bIgoMoyf7pjwfNs5JpX5K-hUgL.FoMEehnEeoqEeoB2dJLoIp7LxKML1KBLBKnLxKqL1hnLBoMNeo5ReozceozX; ALF=1742103657; SUB=_2A25Kqqc5DeRhGeFM61oT8ijOyTiIHXVpyabxrDV8PUJbkNANLWbQkW1NQPhxSzM4WtV2j3cqkmWzeQyRNp28I1Vz'
}
# 使用新的API端点
api_url = f'https://weibo.com/ajax/statuses/show?id={mid}' # 用于获取微博详细信息(包括ID)的API地址
response = requests.get(api_url, headers=headers)
# 检查响应的状态码是否为200(表示请求成功)
if response.status_code != 200:
raise Exception(f"API请求失败,状态码: {response.status_code}")
data = response.json() # 解析API返回的JSON数据
# 如果不包含id,表示API请求未成功获取微博的ID,抛出异常。
if 'id' not in data:
print(f"API返回数据: {data}")
raise Exception("无法获取微博ID")
weibo_id = str(data['id']) # 从JSON数据中提取微博的数字格式ID
# 验证获取到的ID
print(f"原始mid: {mid}")
print(f"转换后的weibo_id: {weibo_id}")
print(f"用户ID: {uid}")
# 验证这是否是正确的微博,打印50个字符作为预览
if 'text' in data:
print(f"微博内容预览: {data['text'][:50]}...")
return weibo_id, uid
except Exception as e:
raise Exception(f"无法从链接中提取信息: {str(e)}\n详细错误: {traceback.format_exc()}")
# 运行主体
weibo_url = input('请输入微博链接(格式如 https://weibo.com/1683472727/Of9fGd3dz):')
try:
weibo_id, uid = extract_weibo_ids(weibo_url)
print(f"确认是否为正确的微博ID和用户ID?")
print(f"微博ID: {weibo_id}")
print(f"用户ID: {uid}")
confirm = input("是否继续爬取?(y/n): ")
# 将用户输入的字符串转换为小写,以确保比较时不区分大小写
if confirm.lower() != 'y':
print("已取消爬取")
exit() # 终止程序运行
# 继续原有的爬取逻辑
max_id = '0'
flag = True
total_comments = 0
while flag:
try:
max_id, is_end = GetContent(max_id, weibo_id, uid)
total_comments += 20 # 每页最多20条
print(f"已爬取评论数: {total_comments}")
if is_end:
print("已到达最后一页或获取完所有评论")
break
time.sleep(random.randint(1, 3)) # 在1-3的范围内生成一个随机整数
except Exception as e:
print(f"爬取过程出错: {e}")
break
print("评论抓取完成!")
f.close() # 关闭文件
except Exception as e:
print(f"Error occurred: {e}")
报错如下
C:\Users\25769\AppData\Local\Programs\Python\Python311\python.exe C:\Users\25769\PycharmProjects\视频录制\视频录制.py
请输入微博链接(格式如 https://weibo.com/1683472727/Of9fGd3dz):https://weibo.com/1683472727/Of9fGd3dz
Error occurred: 无法从链接中提取信息: Expecting value: line 2 column 3 (char 3)
详细错误: Traceback (most recent call last):
File "C:\Users\25769\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\models.py", line 974, in json
return complexjson.loads(self.text, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\25769\AppData\Local\Programs\Python\Python311\Lib\json\__init__.py", line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\25769\AppData\Local\Programs\Python\Python311\Lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\25769\AppData\Local\Programs\Python\Python311\Lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 3 (char 3)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\25769\PycharmProjects\视频录制\视频录制.py", line 138, in extract_weibo_ids
data = response.json() # 解析API返回的JSON数据
^^^^^^^^^^^^^^^
File "C:\Users\25769\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\models.py", line 978, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 2 column 3 (char 3)
进程已结束,退出代码为 0