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

Python中except块未捕获全部错误:NIST API获取CVSS分数异常

问题:调用NIST API计算CVSS分数时异常无法捕获

我正在开发一个通过CVEID为已发现漏洞计算CVSS分数的项目,调用NIST的REST API时频繁因响应格式问题报错。为了调试方便,我想忽略所有错误并排查失败的请求,用了try-except块处理异常,但还是有错误抓不到。下面是我的代码(后来发现是低级错误):

from openpyxl import load_workbook
from urllib import request
import json
from time import sleep

basecolumn = 13
baseline = 1


wb = load_workbook('vulnerabilities.xlsm',keep_vba=True)
ws = wb['CISA Last CVE']
wb.save('Test2.xlsm')

CVEID = "temp"
lineCounter = 0
while CVEID is not None: # While they are vulnerabilities to scan
    lineCounter +=1
    line = baseline+lineCounter
    CVEID = ws.cell(row=line,column=1).value
    if ws.cell(row=line,column=basecolumn).value is None: # Checks if CVE was already scanned previously
        with request.urlopen("https://services.nvd.nist.gov/rest/json/cve/1.0/"+str(CVEID)) as response:
            print(str(CVEID))
            html = response.read()
            responseCVE = html.decode('utf8').replace("'", '"') # Converts to JSON
            responseJSON = json.loads(responseCVE)
            try:
                exploitability = responseJSON['result']['CVE_Items'][0]['impact']['baseMetricV2']['exploitabilityScore']
                impact = responseJSON['result']['CVE_Items'][0]['impact']['baseMetricV2']['impactScore']
            except json.decoder.JSONDecodeError:
                print("first try not working")
                exploitability = responseJSON['result']['CVE_Items'][0]['impact']['baseMetricV3']['exploitabilityScore']
                impact = responseJSON['result']['CVE_Items'][0]['impact']['baseMetricV3']['impactScore']
            except:
                print("Mistery error")

            #print(exploitability)
            #print(impact)
            ws.cell(row=line,column=basecolumn).value = exploitability
            ws.cell(row=line, column=basecolumn+1).value = impact
            sleep(10)
    else :
        print("Already scanned " + str(CVEID) +" vulnerability")
        print(ws.cell(row=line, column=basecolumn).value)
    wb.save('Test2.xlsm')

问题根源

你的代码里有几个明显的低级错误,导致异常无法被捕获:

  1. try-except范围太小:API请求、JSON解析这些最容易抛出异常的操作都在try块外面,比如request.urlopen可能抛出网络错误,json.loads可能抛出解析错误,这些都没被你的try-except覆盖,自然会直接崩溃。
  2. 多余的单引号替换:NIST API返回的是标准JSON格式,你用replace("'", '"')反而会破坏合法的JSON结构(比如字符串里的单引号会被替换),直接导致json.loads报错。
  3. 异常捕获逻辑错误:第一个except捕获的JSONDecodeError只会在json.loads时抛出,但这行代码在try块外面,所以这个分支永远不会触发;而取值时如果遇到键不存在(比如没有baseMetricV2),会抛出KeyError,虽然最后有个万能except,但前面的错误已经让程序终止了。

修正后的代码

from openpyxl import load_workbook
from urllib import request, error
import json
from time import sleep

basecolumn = 13
baseline = 1

wb = load_workbook('vulnerabilities.xlsm', keep_vba=True)
ws = wb['CISA Last CVE']
wb.save('Test2.xlsm')

lineCounter = 0
while True:
    lineCounter += 1
    line = baseline + lineCounter
    CVEID = ws.cell(row=line, column=1).value
    
    # 当CVEID为空时退出循环
    if not CVEID:
        break
    
    if ws.cell(row=line, column=basecolumn).value is None:
        print(f"Processing {CVEID}")
        exploitability = None
        impact = None
        try:
            # 拼接URL时先检查CVEID
            url = f"https://services.nvd.nist.gov/rest/json/cve/1.0/{CVEID}"
            with request.urlopen(url) as response:
                # 直接读取JSON,无需手动解码替换
                responseJSON = json.load(response)
                
                # 先尝试取V2的分数
                if 'result' in responseJSON and 'CVE_Items' in responseJSON['result'] and len(responseJSON['result']['CVE_Items']) > 0:
                    cve_item = responseJSON['result']['CVE_Items'][0]
                    if 'impact' in cve_item:
                        # 优先V2
                        if 'baseMetricV2' in cve_item['impact']:
                            metric = cve_item['impact']['baseMetricV2']
                            exploitability = metric.get('exploitabilityScore')
                            impact = metric.get('impactScore')
                        # V2不存在再试V3
                        elif 'baseMetricV3' in cve_item['impact']:
                            metric = cve_item['impact']['baseMetricV3']
                            exploitability = metric.get('exploitabilityScore')
                            impact = metric.get('impactScore')
        except error.URLError as e:
            print(f"Network error for {CVEID}: {str(e)}")
        except json.JSONDecodeError as e:
            print(f"JSON parse error for {CVEID}: {str(e)}")
        except (KeyError, IndexError) as e:
            print(f"Missing data in response for {CVEID}: {str(e)}")
        except Exception as e:
            print(f"Unexpected error for {CVEID}: {str(e)}")
        
        # 只有成功获取到分数才写入表格
        if exploitability is not None and impact is not None:
            ws.cell(row=line, column=basecolumn).value = exploitability
            ws.cell(row=line, column=basecolumn+1).value = impact
        sleep(10)
    else:
        print(f"Already scanned {CVEID} vulnerability")
        print(ws.cell(row=line, column=basecolumn).value)
    wb.save('Test2.xlsm')

关键修改点

  • 把API请求、JSON解析、分数取值整个流程都放进try块,确保所有异常都能被捕获
  • 去掉了破坏JSON格式的replace("'", '"'),直接用json.load(response)读取响应
  • 明确捕获具体的异常类型(网络错误、解析错误、键/索引错误),方便调试
  • 先检查JSON结构中的键是否存在,避免直接取值抛出KeyError,逻辑更健壮
  • 优化循环条件,当CVEID为空时直接退出,避免无效循环
  • 只有成功获取到分数才写入表格,避免写入空值或错误值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:15:43