You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

json.load读取JSON报JSONDecodeError 嵌套字典存储后读取出错如何解决

错误原因

  • r+模式读写逻辑错误:你使用r+模式打开文件,调用json.load()读取完全部内容后,文件指针会移动到文件末尾,此时直接执行json.dump()不会覆盖原有内容,而是将新的JSON内容追加到原内容之后。下一次读取时,整个文件是多段JSON拼接的非法结构,若某次写入过程中程序异常中断,还会出现空文件,直接触发你遇到的line 1 column 1 (char 0)空内容解析错误。
  • JSON不兼容Python元组类型:你将(title_news, date_news)元组直接存入字典写入JSON,虽然json模块会自动将元组转为列表不会直接触发当前报错,但属于隐藏问题,后续读取出来的结构是列表而非元组,可能导致后续业务逻辑异常。

修复方案

核心修改点

  1. 拆分读写逻辑:放弃r+模式,读操作使用r只读模式,读完直接关闭文件;写操作使用w只写模式,写入前会自动清空原有内容,避免内容追加导致结构异常。
  2. 调整文件操作位置:将文件读写从循环内移到外层,避免每爬一条新闻就频繁读写磁盘,同时降低IO异常概率。
  3. 增加异常兼容:捕获文件不存在、结构损坏的异常,自动初始化字典,避免程序直接崩溃。

修正后代码示例

@tasks.loop(minutes=30)
async def get_gamesnews():
    sites = ['https://multiplayer.it/articoli/notizie/']
    # 程序启动时一次性读取现有数据
    try:
        with open('dictionary_news.json', 'r') as f:
            dict_news = json.load(f)
    except (json.JSONDecodeError, FileNotFoundError):
        # 文件损坏/不存在时自动初始化
        dict_news = {'multiplayer.it': {}}
    
    dictvalues_news = dict_news.get('multiplayer.it', {})
    new_news = [] # 存储需要推送的新新闻

    for site in sites:
        async with aiohttp.ClientSession() as ses:
            async with ses.get(site) as response:
                if response.status == 200:
                    text = await response.text()
                    soup = BeautifulSoup(text, 'lxml')
                    if site == 'https://multiplayer.it/articoli/notizie/':
                        div_news = soup.find_all('div', class_='media-body')
                        for news in div_news:
                            titles = news.find_all('a', class_='text-decoration-none')
                            for title in titles:
                                title_news = title.text.strip()
                                link_news = 'https://multiplayer.it' + title['href']
                                if link_news not in dictvalues_news:
                                    date_news = datetime.date.today().strftime('%Y-%m-%d')
                                    # 转为列表存储,符合JSON格式规范
                                    dict_news['multiplayer.it'][link_news] = [title_news, date_news]
                                    new_news.append((title_news, link_news))
    
    # 所有新闻处理完成后一次性写入文件
    with open('dictionary_news.json', 'w') as f:
        json.dump(dict_news, f, ensure_ascii=False, indent=2)
    
    # 批量推送新新闻
    channel = client.get_channel(855220263917191228)
    for title, link in new_news:
        print((title, link, date_news))
        await channel.send(f'{title} {link}')

内容的提问来源于stack exchange,提问作者Nobodyet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 18:15:05