Documentação facilitada com Python

Olá a todos, este artigo apresentará como usar Python para implementar facilmente a escrita de documentos, reduzir a dificuldade de escrever relatórios e usar o Microsoft Word e pythonbibliotecas python-docxpara simplificar a escrita de relatórios e extrair informações dos relatórios.

Caso

  • Leia um documento do Word e edite-o.

Embora possa não parecer muito interessante, dependendo do sistema suportado, o tempo necessário para produzir relatórios pode ser significativamente reduzido pelo uso inteligente desta configuração. O código é compartilhado e explicado abaixo, mas uma versão base do código está disponível no GitHub. É altamente recomendável modificar o código para atender a casos de uso específicos.

começar

Após utilizar pip3a instalação python-docx, recomenda-se dividir o programa em partes que leiam dois tipos diferentes de conteúdo, nomeadamente parágrafos e tabelas.

def tableSearch(doc):
    """ Takes doc file
Purpose: Scrapes all tables and pulls back text
Returns: Dictionary of tables
"""
    tables = {}
    table = 0
    x = 0
    y = 0

    while 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.font
        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))
                tables[str(table)+"."+str(x)+"."+str(y)] = {"row": x, "column": y, "text": table_test.cell(x,y).text}
                y += 1
            x += 1
            y = 0
        x = 0
        y = 0
        table += 1

    return 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]

parágrafo

A análise dos parágrafos é muito simples. Eles são definidos como uma lista e podem ser acessados ​​de forma semelhante ( doc.paragraphs[n]).

Se você quiser alterar o texto de um parágrafo, basta usar o seguinte código para modificar o texto:

oldText = doc.paragraphs[indexOfParagraph].text

replacedText = oldText.replace("<CLIENT_LONGNAME>",clientLongName)

doc.paragraphs[indexOfParagraph].text = "{} + Text to add".format(oldText)
doc.paragraphs[indexOfParagraph].text = "{} + Replaced text".format(replacedText)

Conforme mencionado acima, você pode fazer isso criando um <CLIENT_LONGNAME>modelo de documento simples contendo palavras-chave como e, em seguida, usando um programa como este para alterar todas as instâncias de cada palavra-chave. Embora isso também possa ser alcançado abrindo um documento e realizando uma operação de localização e substituição, a infraestrutura para dar suporte a essa operação pode tornar o processo rápido de alterações manuais ainda mais rápido.

folha

As tabelas são um pouco mais complicadas, porque as tabelas são bidimensionais, enquanto os parágrafos são unidimensionais (os parágrafos são de 0 a n, enquanto as tabelas têm uma coordenada X e uma coordenada Y). Como as tabelas são tratadas de maneira diferente, é necessária uma maneira mais complexa de percorrer todas as tabelas e indexar algo dentro delas.

Outra observação importante sobre a seleção de elementos em tabelas. Embora a seleção de células exija o uso de valores xe y, você também precisa selecionar a tabela para referência.

table = 0
x = 0
y = 0

while 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 += 1
        x += 1
        y = 0
    x = 0
    y = 0
    table += 1

Iterar um programa como este serve a vários propósitos.

  1. Independentemente da estrutura de cada tabela, o programa percorre cada tabela da mesma maneira.

  2. Gravar e exibir a posição das células permite integrações interessantes.

Um exemplo de integração interessante é a criação de um dicionário contendo valores e suas posições para que as informações possam ser inseridas.

Embora projetar um sistema de consulta para isso esteja além do escopo deste artigo, este artigo fornece uma configuração básica para você começar:

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]

Uso prolongado

Usando o mesmo sistema de loop de antes, você também pode fazer com que um programa analise as informações do relatório concluído e exporte-as para um CSVarquivo para uso em outros programas de elaboração de relatórios. Duas plataformas de elaboração de relatórios que foram usadas e recomendadas neste artigo são PlexTrac e AttackForge. Ambas as plataformas permitem que os resultados da pesquisa sejam importados por meio de um CSVarquivo ou arquivos especialmente formatados.JSON

Como simplificar o processo de importação de informações para outros sistemas/relatórios:

No código acima, há um código que analisa o conteúdo do objeto cada vez que ele percorre um parágrafo ou célula da tabela. Isso não só pode ser usado para depuração, como também adiciona texto a um dicionário. Isso economiza tempo na extração de dados e mais tempo na análise e reformatação dos dados extraídos.

# 段落
fullText = []
# 表格
tables = {}

fullText.append(para.text)
tables[str(table)+"."+str(x)+"."+str(y)] = {"row": x, "column": y, "text": table_test.cell(x,y).text}

Depois de adicionar essas linhas respectivamente, você pode pegar os dados e salvá-los em um formato semelhante ao modo como você acessa os dados. Depois de ter os dados e saber onde encontrá-los, você pode percorrer os respectivos objetos e criar um novo arquivo com os dados.

Como exemplo simples, este artigo adicionará uma função ao código no GitHub para salvar dados em um CSVformato.

import docx
import logging
import argparse
import re
import sys

logging.basicConfig(level=logging.DEBUG)

# 设置日志记录
def get_arg():
    """ Takes nothing
Purpose: Gets arguments from command line
Returns: Argument's values
"""
    parser = argparse.ArgumentParser()
    # CLI 版本
    # parser.add_argument("-d","--debug",dest="debug",action="store_true",help="Turn on debugging",default=False)
    parser.add_argument("-d","--debug",dest="debug",action="store_false",help="Turn on debugging",default=True)
    # 文件版本
    parser.add_argument("-f","--file",dest="file", help="Name of the Word Doc.")
    parser.add_argument("-o","--output",dest="output", help="Name of the file to output the results.")
    options = parser.parse_args()

    if not options.output:
        options.output = "output.csv"
    if not options.file:
        logging.error("Please provide a file name.")
        sys.exit()

    if options.debug:
        logging.basicConfig(level=logging.DEBUG)
        global DEBUG
        DEBUG = True
    else:
        logging.basicConfig(level=logging.INFO)
    return options


def tableSearch(doc):
    """ Takes doc file
Purpose: Scrapes all tables and pulls back text
Returns: Dictionary of tables
"""
    tables = {}
    table = 0
    x = 0
    y = 0

    while 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.font
        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))
                tables[str(table)+"."+str(x)+"."+str(y)] = {"row": x, "column": y, "text": table_test.cell(x,y).text}
                y += 1
            x += 1
            y = 0
        x = 0
        y = 0
        table += 1

    return 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\n"

    for 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:
            continue

    f = 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()

A função precisa ser modificada dependendo do programa que está tentando importar a informação infoToCSV. Embora isso possa ser um pouco chato, os 5 a 20 minutos gastos aqui para adaptar a função às suas necessidades valem a pena quando você precisa produzir vários relatórios. Na minha experiência com este artigo, inserir novamente essas informações manualmente pode rapidamente se tornar entediante.

limitação

Você deve ter notado neste artigo que não há nada tocando nas imagens, e há uma triste razão para isso: ele python-docxnão consegue lidar com arquivos de imagens e parece não notá-los, a menos que você o use ao adicionar eles. Para resolver esse problema, você precisa acessar o código-fonte da biblioteca e integrá-lo ou descompactar .docxo arquivo e analisar a tag da imagem XMLe, em seguida, localizar a imagem na pasta de mídia.

Acho que você gosta

Origin blog.csdn.net/csdn1561168266/article/details/132758077
Recomendado
Clasificación