作者:董帅岭
[TOC]
所有技术和原理都是来源于生活,并且高于生活。咱们所谓的编程什么的,就是按照他们编程涉及的规则、语法。然后按照咱们的思想涉及出来就可以了。
# 一、设计思路
* 按照特定的格式生成log文件。具体什么格式咱们后面慢慢讲,假定咱们已经有了特定格式的log文件。
* 通过Python工具去读取文件,然后按照咱们的想法进行分段,将分段内容放到咱们的word中。当然咱们要提前设计好word文档的格式。
* 所以咱们需要用到的知识就是Python的基本语法,函数,Python操作word。
# 二、函数说明
首先在这里我要感谢一位博主,在博主的指引下学习到了很多东西。同时我也加博主微信了。先把巨人肩膀供上。[https://www.modb.pro/db/31880](https://www.modb.pro/db/31880)
## 自动生成目录
在我们巡检过程中或者自动生成word的过程中,为了方便,可以定义新建一个文件夹里面放我们特定的东西和内容。例如生成的word放在什么位置,自动生成的软件运行log日志放在什么位置等。
函数思路:首先取运行目录,读入目录的最后一个文件夹名字,如果不存在就创建一个,如果存在就跳过。
```
# 生成目录的
def mkdir(path):
import os
path = path.strip()
print(path)
path = path.rstrip("\\")
isExists = os.path.exists(path)
if not isExists:
os.makedirs(path)
return True
else:
return False
```
## 添加word的首页logo图片函数
此函数就是利用的创建单元格,然后再单元格中添加图片,达到居中的目的,应该还有更好的替代语句,不过目前还没有时间研究,后续再进行优化。
```
#添加图片居中函数
def add_center_picture(image_path_or_stream, width=None, height=None):
# run = self.doc.add_paragraph().add_run()
tab = Docx.add_table(rows=1, cols=3) # 添加一个1行3列的空表
cell = tab.cell(0, 1) # 获取某单元格对象(从0开始索引)
ph =cell.paragraphs[0]
run = ph.add_run()
# run.add_break()
run.add_picture(image_path_or_stream, width=width, height=height)
```
## 遍历文件下的所有log文件
此函数从大佬学习的[red\_hope](https://www.modb.pro/u/372611)。大家也可以学习一下。
函数说明:首先获取给定路径,然后通过巡检和判断获取你想要的所有文件路径下的文件名称,方便下一步读取操作。
```
# #目录遍历函数,用于读取目录下所有文件
def list_dir(file_dir):
dir_list = os.listdir(file_dir)
file_r = []
for cur_file in dir_list:
# 准确获取一个txt的位置,利用字符串的拼接
path = os.path.join(file_dir, cur_file)
if cur_file.startswith("Py") & path.endswith(".log"):
file_r.append(path)
return file_r
```
# 三、源码说明
```
import re
from docx import Document
import os
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml
from docx.oxml.ns import qn
from docx.shared import RGBColor
from docx.shared import Pt
from docx.shared import Inches
from docx.enum.text import WD_LINE_SPACING
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
import datetime
from docx.shared import Inches
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT
from docx.shared import Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
# 定义时间
year = datetime.datetime.now().year
month = datetime.datetime.now().month
day = datetime.datetime.now().day
ymd_time = str(year)+'-'+str(month)+'-'+str(day)
# 生成目录的
def mkdir(path):
import os
path = path.strip()
print(path)
path = path.rstrip("\\")
isExists = os.path.exists(path)
if not isExists:
os.makedirs(path)
return True
else:
return False
# 标题用大写数字函数,正规
def num_to_char(num):
"""数字转中文"""
num = str(num)
new_str = ""
num_dict = {"10":u"十","11":u"十一","12":u"十二","13":u"十三","14":u"十四","15":u"十五","16":u"十六","17":u"十七","18":u"十八","19":u"十九","20":u"二十","21":u"二十一","22":u"二十二","23":u"二十三","24":u"二十四","25":u"二十五","26":u"二十六","27":u"二十七","28":u"二十八","29":u"二十九","30":u"十","0": u"零", "1": u"一", "2": u"二", "3": u"三", "4": u"四", "5": u"五", "6": u"六", "7": u"七", "8": u"八","9": u"九"}
listnum = list(num)
# print(listnum)
shu = []
for i in listnum:
# print(num_dict[i])
shu.append(num_dict[i])
new_str = "".join(shu)
# print(new_str)
return new_str
# ####返回标题,巡检日志中我们一般用英文,但是文档必须是中文的
#def get_title(flag_fg):# flag_fg是传入的分隔段,其实也是英文标题
if 'Check file system' in flag_fg:
xj_title_hs = '交换机巡检'
elif 'display fan' in flag_fg:
xj_title_hs = '设备风扇'
elif 'display device power' in flag_fg:
xj_title_hs = '设备电源'
elif 'display environment' in flag_fg:
xj_title_hs = '设备温度'
elif 'display cpu' in flag_fg:
xj_title_hs = '设备CPU'
elif 'display memory' in flag_fg:
xj_title_hs = '设备内存'
elif 'display trapbuffer' in flag_fg:
xj_title_hs = '设备告警缓冲区信息'
elif 'display device' in flag_fg:
xj_title_hs = '设备信息'
elif 'display clock' in flag_fg:
xj_title_hs = '设备时间'
elif 'display current-configuration' in flag_fg:
xj_title_hs = '设备当前配置'
elif 'display users' in flag_fg:
xj_title_hs = '设备用户信息'
elif 'display version' in flag_fg:
xj_title_hs = '设备版本信息'
elif 'display acl all' in flag_fg:
xj_title_hs = '设备ACL信息'
elif 'display interface counters' in flag_fg:
xj_title_hs = '设备接口会话数'
elif 'display stack topology' in flag_fg:
xj_title_hs = '堆叠拓扑'
elif 'display stack configuration' in flag_fg:
xj_title_hs = '设备堆叠配置'
elif 'display stack' in flag_fg:
xj_title_hs = '设备堆叠信息'
elif 'display mac-address total-number' in flag_fg:
xj_title_hs = '设备MAC表总数'
elif 'display arp' in flag_fg:
xj_title_hs = '设备ARP信息'
elif 'display ip routing-table statistics' in flag_fg:
xj_title_hs = '设备路由表总数'
elif 'display ip routing-table' in flag_fg:
xj_title_hs = '设备路由表'
elif 'display logbuffer' in flag_fg:
xj_title_hs = '设备日志'
elif 'display mac' in flag_fg:
xj_title_hs = 'MAC地址信息'
elif 'display interface brief' in flag_fg:
xj_title_hs = '接口摘要'
elif 'display ip interface brief' in flag_fg:
xj_title_hs = '接口IP摘要'
else:
xj_title_hs = flag_fg #很关键,防止穷尽不了英文标题
return xj_title_hs
# #目录遍历函数,用于读取目录下所有文件
def list_dir(file_dir):
dir_list = os.listdir(file_dir)
file_r = []
for cur_file in dir_list:
# 准确获取一个txt的位置,利用字符串的拼接
path = os.path.join(file_dir, cur_file)
if cur_file.startswith("Py") & path.endswith(".log"):
file_r.append(path)
return file_r
# 知识库函数-简例子
#def get_knowledge(str_input):
str_output = [] # 没发现什么,就先输出巡检正常。
str_output_text='巡检正常'
if '[always] madvise never' in str_input:
str_output = ['Linux未关闭透明大页,根据ORACLE安装要求,应关闭透明大页,提升ORACLE 内存及IO读写性能','1111111']
elif 'always madvise [never]' in str_input:
str_output = ['巡检正常:Linux已关闭透明大页','000000']
else:
str_output = ['巡检正常','000000']
return str_output
#添加图片居中函数
def add_center_picture(image_path_or_stream, width=None, height=None):
# run = self.doc.add_paragraph().add_run()
tab = Docx.add_table(rows=1, cols=3) # 添加一个1行3列的空表
cell = tab.cell(0, 1) # 获取某单元格对象(从0开始索引)
ph =cell.paragraphs[0]
run = ph.add_run()
# run.add_break()
run.add_picture(image_path_or_stream, width=width, height=height)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
# 打开文件
file_dir= os.getcwd()+'\\log\\'
file_all = list_dir(file_dir)
for i in range(len(file_all)):
file = file_all[i]
file_full = file.split('\\')
file_str = ''
##截取文件名称,用于报告输出
for value in file_full:
file_name = value
new_filename = file_name.split('.')
for new_value in new_filename:
if 'Py' in new_value:
# print(new_value)
file_str = new_value
f = open(file, 'r',encoding='UTF-8')
lines = f.readlines()
name_line = lines[0]
name_line = name_line.strip()
ip_line = lines[1]
ip_line = ip_line.strip()
#print(name_line)
#print(ip_line)
f.close()
with open(os.getcwd() + '\\config\\Word_conf.ini') as file_conf:
file_conf = file_conf.readlines()
format_file = []
for line in file_conf:
imgfile = line.strip()
format_file.append(imgfile)
#print(format_file)
word_xmmc = format_file[0].rpartition(":")[2]
word_wjmc = format_file[1].rpartition(":")[2]
word_wdbh = format_file[2].rpartition(":")[2]
word_dqbb = format_file[3].rpartition(":")[2]
word_sj = format_file[4].rpartition(":")[2]
word_sp = format_file[5].rpartition(":")[2]
word_cjr = format_file[6].rpartition(":")[2]
word_wdbt = format_file[7].rpartition(":")[2]
#print(word_sp)
f = open(file, 'r', encoding='UTF-8')
# 读取分隔符,写入到list类型的number变量中,关键字就是####
lines = f.readlines()
number = []
for lss in lines:
m = re.findall(r"####", lss)
if m:
number.append(lss)
f.close() ##用完文件关闭是个好习惯
# 创建一个world实例
Docx = Document() #
# 设置正文格式
Docx.styles['Normal'].font.name = '宋体' # 设置文档的基础字体
Docx.styles['Normal'].element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
# 添加word标题 并居中
Docx.add_paragraph('')
Docx.add_paragraph('')
Docx.add_paragraph('')
timu = Docx.add_paragraph('')
run=timu.add_run(word_xmmc)
Docx.paragraphs[3].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
run.bold = True
run.font.size = Pt(20)
# 首页添加那个月份的巡检报告
xj = str(month)+'月'+'-'+name_line+'-巡检报告'
ydxj = Docx.add_paragraph('')
run = ydxj.add_run(xj)
Docx.paragraphs[4].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
run.bold = True
run.font.size = Pt(20)
Docx.add_paragraph('')
Docx.add_paragraph('')
# 添加logo并居中
Docx.paragraphs[6].add_run().add_picture(os.getcwd()+'\\config\\北佳logo.png')
Docx.paragraphs[6].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
Docx.add_paragraph('')
Docx.add_paragraph('')
Docx.add_paragraph('')
Docx.add_paragraph('')
# 填写表格内容
table=Docx.add_table(rows=6,cols=3,style = 'Table Grid')
table.cell(0, 0).text = '文件状态:'
table.cell(1, 0).text = '[ ] 草稿'
table.cell(2, 0).text = '[√] 正式发布'
table.cell(3, 0).text = '[ ] 正在修改'
hb=table.cell(0, 0).merge(table.cell(5, 0))
hb.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
table.cell(0, 1).text = '文件名称:'
table.cell(1, 1).text = '文档编号:'
table.cell(2, 1).text = '当前版本:'
table.cell(3, 1).text = '设 计:'
table.cell(4, 1).text = '审 批:'
table.cell(5, 1).text = '审批日期:'
table.cell(0, 2).text = word_xmmc+xj
table.cell(1, 2).text = word_wdbh
table.cell(2, 2).text = word_dqbb
table.cell(3, 2).text = word_sj
table.cell(4, 2).text = word_sp
table.cell(5, 2).text = str(year)+'年'+str(month)+'月'+str(day)+'日'
wt0 = 3.5
wt1 = 2.5
wt2 = 9.37
table.cell(0, 0).width = Cm(wt0)
table.cell(0, 1).width = Cm(wt1)
table.cell(1, 1).width = Cm(wt1)
table.cell(2, 1).width = Cm(wt1)
table.cell(3, 1).width = Cm(wt1)
table.cell(4, 1).width = Cm(wt1)
table.cell(5, 1).width = Cm(wt1)
table.cell(0, 2).width = Cm(wt2)
table.cell(1, 2).width = Cm(wt2)
table.cell(2, 2).width = Cm(wt2)
table.cell(3, 2).width = Cm(wt2)
table.cell(4, 2).width = Cm(wt2)
table.cell(5, 2).width = Cm(wt2)
Docx.add_paragraph('')
Docx.add_paragraph('')
# 添加首页公司信息
sygs = Docx.add_paragraph('')
run=sygs.add_run('陕西北佳信息技术有限责任公司')
Docx.paragraphs[13].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
run.bold = True
run.font.size = Pt(14)
#首页 添加下面的日期
sysj = Docx.add_paragraph('')
run = sysj.add_run(str(year)+'年'+str(month)+'月')
Docx.paragraphs[14].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
run.bold = True
run.font.size = Pt(14)
Docx.add_page_break()
run = Docx.add_paragraph('')
run = run.add_run('版本说明:')
run.bold = True
run.font.size = Pt(14)
table = Docx.add_table(rows=6, cols=4, style='Table Grid')
table.cell(0, 0).text = '创建/修改人'
table.cell(0, 1).text = '修改时间'
table.cell(0, 2).text = '修改内容'
table.cell(0, 3).text = '备注'
# 首行设置背景色
rows = table.rows[0]
for cell in rows.cells:
shading_elm = parse_xml(r'<w:shd {} w:fill="D9D9D9"/>'.format(nsdecls('w')))
cell._tc.get_or_add_tcPr().append(shading_elm)
table.cell(1, 0).text = word_cjr
table.cell(1, 1).text = str(year)+'年'+str(month)+'月'+str(day)+'日'
table.cell(1, 2).text = '建立'
table.cell(1, 3).text = ''
Docx.add_page_break()
# 再打开文件,开始正式读取巡检内容
f = open(file, 'r', encoding='UTF-8')
buff = f.read()
# 将多余的SQL>格式去掉
# for a in buff:
buff = buff.replace('SQL>', '')
buff = buff.replace('\r', '')
# 现在表格中输出巡检数据库基本信息:
run = Docx.add_heading('', level=1).add_run(word_wdbt)
run.font.name = u'宋体'
run._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
# 做个表格,放入巡检机器的基本信息
table_1 = Docx.add_table(rows=3, cols=2, style='Table Grid')
table_1.cell(0,0).text = '设备名称'
table_1.cell(0,1).text = name_line
table_1.cell(1, 0).text = '设备IP'
table_1.cell(1,1).text = ip_line
table_1.cell(2, 0).text = '备注'
xj_title = "" #world的各级标题变量
#wt_all = [] # 记录巡检发现问题的列表
# 开始循环读取巡检结果
for j in range(len(number)):
k = j + 1 # 只所以要设置K,是为了防止和j溢出,因为最后一行是没有j+1的
if k < len(number):
#print(len(number))
fenge1 = number[j]
fenge2 = number[j + 1]
fenge1 = fenge1.replace('\n', '')
print(f'{k}:开始查找{fenge1}相关的内容')
xj_title = fenge1.replace('####','')
#if xj_title == 'PLNOCHECK':
# 遇到不检查项目,跳出本次循环
#continue
daxie = num_to_char(k)
title = f'{k}、{xj_title}'
run1 = Docx.add_heading('',level=1).add_run(title)
run1.font.name = u'宋体'
run1._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
#Docx.add_heading("1、巡检信息:", level=2)
pat = re.compile(fenge1 + '(.*)' + fenge2, re.S)
result = pat.findall(buff)
match_list = []
for match1 in result:
#print(match1)
match_list=match1.split('\n###')
#print(match_list)
match_ml = match_list[1]
match_ml = match_ml.rstrip()
match_ml = match_ml.lstrip()
#print(match_ml)
match_jg = match_list[2]
match_jg = match_jg.rstrip()
match_jg = match_jg.lstrip()
#print(match_jg)
#match1 = match1.replace('\n\n', '')
##中间多余的信息删除
#match1 = match1[:match1.rfind('CHECKJCSQL')]
#match1 = match1.rstrip()
#match1 = match1.lstrip()
##中间多余的信息删除完成
table = Docx.add_table(rows=3, cols=2, style='Table Grid')
table.cell(0, 0).width = Cm(2.2)
table.cell(1, 0).width = Cm(2.2)
table.cell(2, 0).width = Cm(2.2)
table.rows[0].height = Cm(2)
table.rows[2].height = Cm(4)
cell = table.cell(0, 0)
p = cell.paragraphs[0]
run = p.add_run('巡检命令')
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
cell = table.cell(0, 1)
p = cell.paragraphs[0]
fen = match_ml
run = p.add_run(fen)
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
cell = table.cell(1, 0)
p = cell.paragraphs[0]
run = p.add_run('巡检内容')
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
cell = table.cell(1, 1)
p = cell.paragraphs[0]
run = p.add_run(match_jg)
run.font.size = Pt(9)
cell = table.cell(2, 0)
p = cell.paragraphs[0]
run = p.add_run('结果分析')
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
cell = table.cell(2, 1)
p = cell.paragraphs[0]
run = p.add_run(' □正常 □异常')
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.TOP
table.cell(0, 0).width = Cm(2.2)
table.cell(1, 0).width = Cm(2.2)
table.cell(2, 0).width = Cm(2.2)
table.cell(0, 1).width = Cm(13.4)
table.cell(1, 1).width = Cm(13.4)
table.cell(2, 1).width = Cm(13.4)
table.rows[0].height = Cm(2)
table.rows[2].height = Cm(2)
#Docx.add_heading("问题汇总:", level=1)
#for k in range(len(wt_all)):
#Docx.add_heading(f'{k+1}.{wt_all[k]}',level=3)
yemei = Docx.sections[0].header
par = yemei.paragraphs[0]
par.add_run(word_xmmc)
par.alignment = WD_ALIGN_PARAGRAPH.CENTER
sec1 = Docx.sections[0]
sec1.different_first_page_header_footer = True
yejiao = Docx.sections[0].footer
par0 = yejiao.paragraphs[0]
run0=par0.add_run('陕西北佳信息技术有限责任公司 地址:西安市雁塔路67号红锋商务大厦8层')
run0.font.size = Pt(9)
par0.paragraph_format.space_after = Pt(0)
par1 = yejiao.add_paragraph('')
run1 = par1.add_run('联系电话:(029) 85511000 4000184818 传真:(029)85510292')
run1.font.size = Pt(9)
par1.paragraph_format.space_after = Pt(0)
par2 = yejiao.add_paragraph('')
run2 = par2.add_run('网址:http://www.beijiait.com')
run2.font.size = Pt(9)
par2.paragraph_format.space_after = Pt(0)
# 设置工程师签字的地方
Docx.add_paragraph('')
Docx.add_paragraph('')
table_qz = Docx.add_table(rows=2, cols=1)
table_qz.cell(0,0).text = '工程师签字:'
table_qz.cell(1, 0).text = '日 期:'
table_qz.rows[0].height = Cm(0.5)
table_qz.rows[1].height = Cm(0.5)
# print(file_str)
mkdir(os.getcwd()+"\\word")
Docx.save(os.getcwd()+'\\word\\'+name_line+'_巡检报告'+ymd_time+'.docx')
f.close()
```