作者:董帥嶺
[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()
```