说明
@MrxMyx
本文核心代码都是引用 MrxMyx的内容,其内容详见LDRA Testbed系列(二)Testbed软件静态分析_自动提取静态分析数据生成文档
主要是在前人的基础上,我把读取配置信息,调整excel格式等补充了补充。
代码部分
首先是config.ini,这是一个示例
; config.ini
[DEFAULT]
SoftwareVersion = 1.0.0
CheckTime = 2024-05-17
DevelopmentEngineer = xxx
TestEngineer = xxx
[RULES]
RuleNumList = 101,102,103,113S
RuleDescriptionList = Rule1,Rule2,Rule3,Non standard character
[PATH]
ViolationHtmPath = .
配置文件及配置函数
#config.py
import configparser
class Config():
def __init__(self):
self.software_version = None
self.check_time = None
self.development_engineer = None
self.test_engineer = None
self.rule_num_list = None
self.rule_description_list = None
self.violation_htm_path = None
def read_config(self):
# 创建配置解析器
config = configparser.ConfigParser()
# 读取配置文件
config.read('config.ini')
# 读取全局变量
self.software_version = config.get('DEFAULT', 'SoftwareVersion')
self.check_time = config.get('DEFAULT', 'CheckTime')
self.development_engineer = config.get('DEFAULT', 'DevelopmentEngineer')
self.test_engineer = config.get('DEFAULT', 'TestEngineer')
# 读取规则相关配置
self.rule_num_list = config.get('RULES', 'RuleNumList').split(',')
self.rule_description_list = config.get('RULES', 'RuleDescriptionList').split(',')
# 读取文件路径
self.violation_htm_path = config.get('PATH', 'ViolationHtmPath')
核心代码
#html_parse.py
import re
import xlwt
import glob
import os
from config import Config
"""读取配置信息"""
config = Config()
class ExcelStyle:
style_list = xlwt.easyxf('font: name Arial; align: wrap on, vert centre, horiz center')
style_title = xlwt.easyxf('font: name Arial, bold on; align: wrap on, vert centre, horiz center')
#写入固定内容
def WriteConst(sheet, line_num ):
sheet.write(line_num,0,line_num,ExcelStyle.style_list) #写入序号
sheet.write(line_num,7,config.software_version,ExcelStyle.style_list) #写入被测软件版本
sheet.write(line_num,8,config.check_time,ExcelStyle.style_list) #写入检查时间
sheet.write(line_num,9,config.development_engineer,ExcelStyle.style_list) #写入开发人员
sheet.write(line_num,12,config.test_engineer,ExcelStyle.style_list) #写入测试人员
#写入规则编号
def write_rule_num(sheet,i,rule_description):
rule_idx = 0
if 'Non standard character' in rule_description: #因违规的特殊字符不确定,此处做特殊处理
sheet.write(i,4,'113S',ExcelStyle.style_list)
return
for rule in config.rule_description_list:
if rule in rule_description:
sheet.write(i,4,config.rule_num_list[rule_idx],ExcelStyle.style_list)
break
rule_idx += 1
if (rule_idx == len(config.rule_num_list)):
sheet.write(i,4,'--',ExcelStyle.style_list)
#特殊字符处理
def special_char_deal(string):
new_str = string.replace('<','<')
new_str = new_str.replace('>','>')
new_str = new_str.strip()
return new_str
def get_file(path, pattern):
search_pattern = os.path.join(path, pattern)
# 使用 glob 查找匹配模式的文件
matching_files = glob.glob(search_pattern)
# 返回第一个匹配的文件,如果没有文件匹配则返回 None
if matching_files:
return matching_files[0]
else:
return None
#主函数
def violation_main():
#初始化
i=1
file_line_num=0
globals_flag = 0
globals_start = 0
func_flag = 0
func_start = 0
print('Executing...')
config.read_config()
#新建一个excel文件
file=xlwt.Workbook(encoding='utf-8',style_compression=0)
#新建一个sheet
sheet=file.add_sheet('violations')
#写入表头
list_title = ["序号","文件名","函数名","行数","违规编号","违规说明","违规等级","软件版本","检查时间","开发人员","研发确认","处理方式","测试人员","违规状态","备注"]
for j in range(0,15):
sheet.write(0,j,list_title[j],ExcelStyle.style_title)
htm_file = get_file(config.violation_htm_path,"*.rps.htm*")
if htm_file != 0:
with open(htm_file,'r',errors='ignore') as fopen_r:
lines=fopen_r.readlines()
#写入violations
for line in lines:
file_line_num += 1 #当前读取的文件行数(用于调试)
if line.find("Globals / code outside procedures") != -1:
globals_flag = 1
#开始写入Globals / code outside procedures部分的violations
if globals_flag == 1 and line.find("File: Src Line") != -1:
globals_start = 1
if globals_start == 1:
searchObj_nofunc = re.search(r'<TR><td align=center> <a name=.*>(.*?)</a> </td><td > (.*?)\: (.*?) </td><td > (.*?) </td>',line,re.I) #获取文件名、违规 9.4这里是a name=.
if searchObj_nofunc != None:
sheet.write(i,1,searchObj_nofunc.group(2),ExcelStyle.style_list) #写入文件名
sheet.write(i,3,searchObj_nofunc.group(3),ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_nofunc.group(4))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_nofunc.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,'——',ExcelStyle.style_list) #写入函数名'--'
WriteConst(sheet,i) #写入其他固定项
i = i+1
else:
searchObj_nofunc = re.search(r'<TR><td align=center> (.*?) </td><td > (.*?)\: (.*?) </td><td > (.*?) </td>',line,re.I) #获取文件名、行数、违规
if searchObj_nofunc != None:
sheet.write(i,1,searchObj_nofunc.group(2),ExcelStyle.style_list) #写入文件名
sheet.write(i,3,searchObj_nofunc.group(3),ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_nofunc.group(4))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_nofunc.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,'——',ExcelStyle.style_list) #写入函数名'--'
WriteConst(sheet,i) #写入其他固定项
i = i+1
else:
searchObj_nofunc = re.search(r'<TR><td align=center> (.*?) </td><td > (.*?) </td><td > (.*?) </td>',line,re.I) #获取文件名、违规
if searchObj_nofunc != None:
sheet.write(i,1,searchObj_nofunc.group(2),ExcelStyle.style_list) #写入文件名
sheet.write(i,3,'——',ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_nofunc.group(3))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_nofunc.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,'——',ExcelStyle.style_list) #写入函数名'--'
WriteConst(sheet,i) #写入其他固定项
i = i+1
#其实还有一种情况,这里就不考虑了,就是网页中Violation那块没数据。
if line.find("Top of Report") != -1:
globals_flag = 0 #结束写入Globals / code outside procedures部分的violations
globals_start = 0
func_flag = 1
#开始写入函数部分的violations
if func_flag == 1 and line.find("<CENTER><TABLE BORDER WIDTH=50%><TR><TH BGCOLOR=\"#FF0000\">") != -1:
func_start = 1
searchObj_filefunc = re.search(r"<a href=(.*?)> (.*?)<BR>(.*?) to (.*?)\s(.*?)\) - FAIL",line,re.I) #获取文件名和函数名
if searchObj_filefunc != None:
file_name = searchObj_filefunc.group(5)
func_name = searchObj_filefunc.group(2)
else:
searchObj_filefunc = re.search(r"size='5'> (.*?)<BR>(.*?) to (.*?)\s(.*?)\) - FAIL",line,re.I) #获取文件名和函数名
if searchObj_filefunc != None:
file_name = searchObj_filefunc.group(4)
func_name = searchObj_filefunc.group(1)
if func_start == 1:
searchObj_func = re.search(r'<TR><td align=center> <a id=.*>(.*?)</a> </td><td align=center> (.*?) </td><td > (.*?) </td>',line,re.I) #获取行数和违规
if searchObj_func != None:
sheet.write(i,1,file_name,ExcelStyle.style_list) #写入文件名
sheet.write(i,3,searchObj_func.group(2),ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_func.group(3))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_func.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,func_name,ExcelStyle.style_list) #写入函数名
WriteConst(sheet,i) #写入其他固定项
i = i+1
else:
searchObj_func = re.search(r'<TR><td align=center> (.*?) </td><td align=center> (.*?) </td><td > (.*?) </td>',line,re.I) #获取行数和违规
if searchObj_func != None:
sheet.write(i,1,file_name,ExcelStyle.style_list) #写入文件名
sheet.write(i,3,searchObj_func.group(2),ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_func.group(3))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_func.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,func_name,ExcelStyle.style_list) #写入函数名
WriteConst(sheet,i) #写入其他固定项
i = i+1
else:
searchObj_func = re.search(r'<TR><td align=center> (.*?) </td><td > (.*?) </td><td > (.*?) </td>',line,re.I) #获取行数和违规
if searchObj_func != None:
sheet.write(i,1,file_name,ExcelStyle.style_list) #写入文件名
sheet.write(i,3,searchObj_func.group(2),ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_func.group(3))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_func.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,func_name,ExcelStyle.style_list) #写入函数名
WriteConst(sheet,i) #写入其他固定项
i = i+1
else:
searchObj_func = re.search(r'<TR><td align=center> (.*?) </td><td > (.*?) </td>',line,re.I) #获取违规(没有行数的特殊情况)
if searchObj_func != None:
sheet.write(i,1,file_name,ExcelStyle.style_list) #写入文件名
sheet.write(i,3,'——',ExcelStyle.style_list) #写入文件行数
rule_description = special_char_deal(searchObj_func.group(2))
write_rule_num(sheet,i,rule_description) #写入规则编号
sheet.write(i,5,rule_description,ExcelStyle.style_list) #写入不合格项
sheet.write(i,6,searchObj_func.group(1),ExcelStyle.style_list) #写入违规等级
sheet.write(i,2,func_name,ExcelStyle.style_list) #写入函数名
WriteConst(sheet,i) #写入其他固定项
i = i+1
if line.find('<a href="#top_of_rep">Top of Report</a>') != -1:
func_start = 0 #结束写入当前函数的violations
if line.find("Standards violations for procedures are printed in tables with code markers as follows") != -1:
func_flag = 0 #结束写入函数部分的violations
file.save('Violations_Report.xls')
print("execute success")
# 调用主函数
if __name__ == "__main__":
violation_main()