网站建立网站,书画网站模板asp,代码编程入门,wordpress文章搬家大家好#xff0c;本文将介绍如何使用Python轻松实现文档编写#xff0c;减少报告撰写的痛苦#xff0c;使用Microsoft Word、python和python-docx库来简化报告撰写和从报告中提取信息。
案例 读取一个Word文档并进行编辑。
虽然听起来可能不那么令人振奋#xff0c;但根…大家好本文将介绍如何使用Python轻松实现文档编写减少报告撰写的痛苦使用Microsoft Word、python和python-docx库来简化报告撰写和从报告中提取信息。
案例 读取一个Word文档并进行编辑。
虽然听起来可能不那么令人振奋但根据支持系统的不同可以通过巧妙运用这个设置来大大减少制作报告所需的时间。代码将在下面分享和解释但用户可以在GitHub上获取代码的基础版本。强烈建议根据特定用例修改代码以适应具体使用情况。
开始
在使用pip3安装python-docx之后建议将程序拆分为读取两种不同类型内容的部分即段落和表格。
def tableSearch(doc): Takes doc file
Purpose: Scrapes all tables and pulls back text
Returns: Dictionary of tables
tables {}table 0x 0y 0while table ! len(doc.tables):logging.debug(Table {} Row: {}.format(table, len(doc.tables[table].rows)))logging.debug(Table {} Column: {}.format(table, len(doc.tables[table].columns)))logging.debug(Table {}.format(table))table_test doc.tables[table]run doc.add_paragraph().add_run()font run.fontwhile x ! len(table_test.rows):while y ! len(table_test.columns):logging.debug(Table: {}, X: {}, Y: {}\n{}\n.format(table, x,y,table_test.cell(x,y).text))tables[str(table).str(x).str(y)] {row: x, column: y, text: table_test.cell(x,y).text}y 1x 1y 0x 0y 0table 1return tables# 读取Word文档
def wordDocx(file): Takes file
Purpose: Reads the Word Doc
Returns: Nothing
logging.debug(File: {}.format(file))doc docx.Document(file)fullText []for para in doc.paragraphs:logging.debug(Paragraph: {}.format(para.text))fullText.append(para.text)tableInfo tableSearch(doc)return [fullText, tableInfo]
段落
段落的解析非常简单。它们被设置为一个列表可以以类似的方式访问doc.paragraphs[n]。
如果想更改段落中的文本只需使用下面的代码即可修改文本:
oldText doc.paragraphs[indexOfParagraph].textreplacedText oldText.replace(CLIENT_LONGNAME,clientLongName)doc.paragraphs[indexOfParagraph].text {} Text to add.format(oldText)
doc.paragraphs[indexOfParagraph].text {} Replaced text.format(replacedText)
正如上文所述可以通过制作一个包含关键词如CLIENT_LONGNAME的普通文档模板然后使用类似这样的程序去更改每个关键词的所有实例。虽然这也可以通过打开文档并执行查找和替换操作来实现但支持此操作的基础结构可以使手动更改的快速过程变得更快。
表格
表格要稍微复杂一些原因在于表格是二维的而段落是一维的段落是0至n的而表格有一个X坐标和一个Y坐标。由于表格的处理方式不同因此需要一种更复杂的方式来循环遍历所有表格并索引其中的某些内容。
关于在表格中选择元素的另一个重要注意事项。虽然选择单元格需要使用x和y值但还需要选择要引用的表格。
table 0
x 0
y 0while table ! len(doc.tables):table_test doc.tables[table]while x ! len(table_test.rows):while y ! len(table_test.columns):logging.debug(Table: {}, X: {}, Y: {}\n{}\n.format(table, x,y,table_test.cell(x,y).text))y 1x 1y 0x 0y 0table 1
像这样对程序进行迭代有多个目的。 不论每个表格的结构如何程序都会以相同方式循环遍历每个表格。 记录和显示单元格的位置可以进行有趣的集成。
一个有趣集成的例子是创建包含值及其位置的字典以便插入信息。
虽然为此设计一个查询系统超出了本文的讨论范围但本文已经提供了一个基本设置可以帮助你入门
ref {
Date: [0,2,12]
}info {
Date: 08/24/2023
}for key,value in ref.items:if table value[0] and x value[1] and y value[2]:table_test.cell(x,y).text info[key]
扩展用途
使用与前面相同的循环系统还可以让某个程序解析已完成报告中的信息并将其导出为CSV文件以便在其他报告撰写程序中使用。本文使用过并推荐的两个报告撰写平台是PlexTrac和AttackForge。这两个平台都允许通过一个特殊格式的CSV文件或JSON文件导入调查结果。
如何简化向其他报告/系统导入信息的过程
在上面的代码中每次循环遍历段落或表格中的一个段落或单元格时都会有代码可以查看对象中的内容。这不仅可以用于调试本文将文本添加到字典中。这样可以节省从中提取数据的时间而将更多时间用于解析和重新格式化提取回来的数据。
# 段落
fullText []
# 表格
tables {}fullText.append(para.text)
tables[str(table).str(x).str(y)] {row: x, column: y, text: table_test.cell(x,y).text}分别添加这几行后就可以抓取数据并以类似于访问数据的格式保存数据。一旦获得了数据并知道在哪里可以找到它就可以在各自的对象中循环遍历并使用这些数据创建一个新文件。
举个简单的例子本文将在GitHub上的代码中添加一个函数将数据保存为CSV格式。
import docx
import logging
import argparse
import re
import syslogging.basicConfig(levellogging.DEBUG)# 设置日志记录
def get_arg(): Takes nothing
Purpose: Gets arguments from command line
Returns: Arguments values
parser argparse.ArgumentParser()# CLI 版本# parser.add_argument(-d,--debug,destdebug,actionstore_true,helpTurn on debugging,defaultFalse)parser.add_argument(-d,--debug,destdebug,actionstore_false,helpTurn on debugging,defaultTrue)# 文件版本parser.add_argument(-f,--file,destfile, helpName of the Word Doc.)parser.add_argument(-o,--output,destoutput, helpName of the file to output the results.)options parser.parse_args()if not options.output:options.output output.csvif not options.file:logging.error(Please provide a file name.)sys.exit()if options.debug:logging.basicConfig(levellogging.DEBUG)global DEBUGDEBUG Trueelse:logging.basicConfig(levellogging.INFO)return optionsdef tableSearch(doc): Takes doc file
Purpose: Scrapes all tables and pulls back text
Returns: Dictionary of tables
tables {}table 0x 0y 0while table ! len(doc.tables):logging.debug(Table {} Row: {}.format(table, len(doc.tables[table].rows)))logging.debug(Table {} Column: {}.format(table, len(doc.tables[table].columns)))logging.debug(Table {}.format(table))table_test doc.tables[table]run doc.add_paragraph().add_run()font run.fontwhile x ! len(table_test.rows):while y ! len(table_test.columns):logging.debug(Table: {}, X: {}, Y: {}\n{}\n.format(table, x,y,table_test.cell(x,y).text))tables[str(table).str(x).str(y)] {row: x, column: y, text: table_test.cell(x,y).text}y 1x 1y 0x 0y 0table 1return tables# 读取word文档
def wordDocx(file): Takes file
Purpose: Reads the Word Doc
Returns: Nothing
logging.debug(File: {}.format(file))doc docx.Document(file)fullText []for para in doc.paragraphs:logging.debug(Paragraph: {}.format(para.text))fullText.append(para.text)tableInfo tableSearch(doc)return [fullText, tableInfo]def infoToCSV(para, table): Takes a list and a dictionary
Purpose: Convert dictionary and paragraph into a CSV file
Returns: Nothing
csvHeaders Name,Description,Recommendation\nfor key, values in table.items():Name Description Recommendation nameRegex re.search(0\.\d\.1,key) desRegex re.search(0\.\d\.3,key)recRegex re.search(0\.\d\.6,key)if nameRegex:Name value[text]if desRegex:Description value[text]if recRegex:Recommendation value[text] csvHeaders {},{},{}\n.format(Name,Description,Recommendation)for item in para:values re.findall(Name\:\(.?)\.?Description\:\(.?)\.?Recommendation\:\(.?)\,item)try:csvHeaders {},{},{}\n.format(values[0],values[1],values[2])except IndexError:continuef open(Output.csv, w)f.write(csvHeaders)f.close()def main():options get_arg()logging.debug(Options: {}.format(options))info wordDocx(options.file)logging.debug(Info: {}.format(info))infoToCSV(info[0], info[1])if __name__ __main__:main()需要根据尝试要导入信息的程序来修改infoToCSV函数。虽然这可能有点烦人但在必须制作多份报告时在这里花费的5-20分钟来使函数适应需求是值得的。根据本文的经验手动重新输入这些信息很快就会变得非常枯燥。
局限性
在本文中你可能已经注意到没有涉及图片的任何内容这有一个令人遗憾的原因python-docx无法处理图片文件除非在添加图片时使用它否则它似乎根本不会注意到图片文件。要解决这个问题要么需要进入库的源代码并对其进行集成要么需要解压缩.docx文件并解析图像标签的XML然后从媒体文件夹中查找图片。