m0_73899719 2025-05-07 11:29 采纳率: 100%
浏览 18
已结题

(附代码)微博评论爬虫程序成功后出现报错Error occurred: 无法从链接中提取信息: Expecting value: line 2 column 3 (char 3)

本人为文科生尝试编程,学过一点点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
  • 写回答

4条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-05-07 11:33
    关注

    让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。
    如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!

    根据错误信息和代码分析,问题出在 extract_weibo_ids 函数中解析微博API返回的JSON数据时。错误 Expecting value: line 2 column 3 (char 3) 表明服务器返回的不是有效的JSON数据。

    问题原因

    1. Cookie失效:微博的Cookie通常有效期较短(几小时到几天),您代码中的Cookie可能已过期
    2. 反爬机制:微博可能检测到爬虫行为,返回了非JSON内容(如验证页面)
    3. API变更:微博可能调整了API接口或参数要求

    解决方案

    1. 更新Cookie

    请按以下步骤获取最新Cookie:

    # 获取最新Cookie方法:
    # 1. 浏览器登录微博
    # 2. 打开开发者工具(F12)->Network
    # 3. 刷新页面,找到任意weibo.com的请求
    # 4. 复制Request Headers中的Cookie
    

    2. 修改请求头

    建议添加更多请求头模拟浏览器:

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Cookie': 'YOUR_NEW_COOKIE_HERE',  # 必须更新
        'Referer': 'https://weibo.com/',
        'X-Requested-With': 'XMLHttpRequest'
    }
    

    3. 添加错误处理

    修改 extract_weibo_ids 函数增加响应检查:

    def extract_weibo_ids(url):
        try:
            # ...原有代码...
            response = requests.get(api_url, headers=headers)
            
            # 新增响应检查
            print(f"API响应状态码: {response.status_code}")
            print(f"响应内容前200字符: {response.text[:200]}")
            
            if response.status_code != 200:
                raise Exception(f"API请求失败,状态码: {response.status_code}")
            
            data = response.json()
            # ...后续代码...
    

    4. 完整修改建议

    建议改用更稳定的API调用方式:

    def extract_weibo_ids(url):
        try:
            # 直接从移动端API获取信息(更稳定)
            mid = url.split('/')[-1]
            api_url = f'https://m.weibo.cn/statuses/show?id={mid}'
            
            headers = {
                'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
                'Cookie': 'YOUR_MOBILE_COOKIE'  # 需要获取移动端cookie
            }
            
            response = requests.get(api_url, headers=headers)
            if 'data' not in response.json():
                raise Exception("API返回数据格式异常")
                
            data = response.json()['data']
            return str(data['id']), str(data['user']['id'])
            
        except Exception as e:
            raise Exception(f"链接解析失败: {str(e)}")
    

    调试建议

    1. 先单独测试链接解析功能:

      # 测试代码
      test_url = "https://weibo.com/1683472727/Of9fGd3dz"
      try:
       print(extract_weibo_ids(test_url))
      except Exception as e:
       print(f"测试失败: {e}")
      
    2. 如果仍失败,可以尝试:

    • 使用移动端API(m.weibo.cn)
    • 添加代理IP
    • 降低请求频率

    注意事项

    1. 微博反爬严格,建议:

      • 每次运行前更新Cookie
      • 添加随机延迟(您代码中已有)
      • 控制爬取速度(建议3-5秒/请求)
    2. 如果持续失败,可能需要考虑:

      • 使用微博官方API(需申请权限)
      • 改用Selenium模拟浏览器操作

    需要进一步帮助可以提供:

    • 最新的响应内容(隐藏敏感信息)
    • 您尝试的微博链接(如果不是敏感内容)
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 5月17日
  • 已采纳回答 5月9日
  • 创建了问题 5月7日