Imagine que você tem uma série de documentos em pdf, ou mesmo outro arquivo pdf, para mesclar e manter tudo em apenas um arquivo.
Vamos fazer isso com REGEX e PyPDF2 com python
Você, assim como eu, já foi em sites que mesclam PDF. Mas e se você puder fazer isso de graça com Python? Ou ainda criar seu próprio site para hospedar esse “concatenador” de pdf?
É isso que vamos fazer agora! Nesse projeto, vamos concatenar arquivos PDF com base na data contida no nome do arquivo.
Startando o Projeto – Bibiotecas REGEX e PyPDF2
Vamos usar as libs PyPDF2, re e os. Com exceção da PyPDF2, tanto a lib os como a re são módulos padrão do Python. Sendo assim, já vem instalada.
Então, a unica a ser instalada neste caso é a PyPDF2. Execute a seguinte instalação em seu ambiente virtual.
pip install PyPDF2
Dentro do código, você vai importa-las dessa forma:
Função de extração da data com re – Regular Expression
Aqui vamos usar a função search da lib re para encontrar as ocorrências do padrão na string.
A string em nosso caso, é o nome do arquivo.
Definimos o padrão usando raw string para que o Python não interprete caracteres especiais em nosso padrão.
pattern = r'\d{4}-\d{2}-\d{2}'
Uma vez definido o padrão, executados a busca e recebemos o resultado. O nosso resultado retornado é composto pela classe Macth da lib re.
Com ela podemos usar diversos métodos que recuperam as infos da busca pelo padrão, tais como: posição, string, início e fim do padrão.
Caso tenhamos um resultado em mãos, iremos executar o método group() que retorna a parte inteira da string que casou com a expressão. Caso contrário, retornamos None.
Da uma olhada em como ficou a função:
def extract_date_from_filename(filename):
# Utiliza expressão regular para extrair a data do nome do arquivo
pattern = r'\d{4}-\d{2}-\d{2}' # Formato de data esperado YYYY-MM-DD
match = re.search(pattern, filename)
if match:
return match.group()
return None
Ordenando Arquivos baseado em padrão de string – Data
Agora, vamos usar a data extraida do nomes do arquivos para ordernar nossa lista de arquivos.
O primeiro pedaço de código usa um for para colocar dentro de uma lista todos os arquivos de um diretório.
Esse for em uma linha melhora a legibilidade do código e diminui o número de linhas necessárias.
Neste caso, estamos verificando os items dentro do directoy_path e adicionando a lista apenas se o f for um arquivo.
Após a criação da nossa lista (pdf_files_with_date) que receberá as tuplas, vamos chamar os métodos anteriores.
def sorting_files_by_date(directory_path):
files = [f for f in os.listdir(directory_path)
if os.path.isfile(os.path.join(directory_path, f))]
# var lista de tuplas
pdf_files_with_date = []
for file in files:
if file.lower().endswith('.pdf'):
date = extract_date_from_filename(file)
if date:
# tupla: (filename, data_padrao)
pdf_files_with_date.append((file, date))
return sorted(pdf_files_with_date, key=lambda x: x[1])
Verificamos se os arquivos são pdf com o método de string endswith(). Caso verdadeiro chamamos a função extract_data_from_file(file), passando o nome do arquivo atual como parâmetro.
Caso haja uma data (correspondente ao padrão) adicionamos a tupla (nome_do_arquivo, data_encontrada) a lista.
Após a varredura a função sorted irá ordernar a lista a parte de uma key (chave).
Ficou confuso com o lambda na história? Então, vamos entender melhor.
Key recebe a função lambda que permite verificar o segundo elemento da tupla.
Neste caso, x é um elemento da lista. Já que a lista é formada por tuplas, seremos capazes de acessar seus items pelos indices 0 e 1.
Sendo assim, x[0] seria o primeiro item, o nome do arquivo. Já x[1] consiste no segundo elemento, a data associada ao arquivo.
Ordenando pela data seremos capazes de mesclar os arquivos desse diretório da maneira correta.
Perceba que a lista realocada toda vez que chamamos a função para um novo subdiretório. Assim, não teremos sobreposição de listas.
Função de concatenação dos PDFs
Vamos então mesclar os arquivos que recebemos para realizar o trabalho de freela.
Neste caso, precisamos criar uma nova estrutura igual a original para que os arquivos pdf estão corretamente associados a cada diretório.
Mas, antes disso vamos ordernar nossos arquivos de cada subdiretório.
Você vai perceber que a var pdf_files_sorted_by_date está recebendo justamente esses arquivos já ordernados.
O próximo passo está em alocar a classe PdfMerger(). Para que possamos adicionar os arquivos a serem escritos em um único arquivo destino.
pdf_files_sorted_by_date = sorting_files_by_date(directory_path)
merger = PyPDF2.PdfMerger()
Então, cada arquivo pdf da nossa lista será adicionado ao merger. Lembre-se de adicionar o caminho completo.
def merge_pdfs_sorted_by_date(directory_path, output_file='mesclados.pdf'):
pdf_files_sorted_by_date = sorting_files_by_date(directory_path)
merger = PyPDF2.PdfMerger()
for file, _ in pdf_files_sorted_by_date:
file_path = os.path.join(directory_path, file)
merger.append(file_path)
new_path = '/'.join(['arquivos_mesclados', directory_path.split('/')[1]])
if not os.path.exists(new_path):
os.makedirs(new_path)
output_path = os.path.join(new_path, output_file)
with open(output_path, 'wb') as output:
merger.write(output)
print(f'Arquivos PDF foram mesclados e salvo como {output_file} em {new_path}')
Se você não precisa manter a mesma estrutura da original, após o merge bastaria escrever o merger.write().
Mas no meu caso, o cliente queria dessa forma. Então….
#definimos o novo caminho e criamos caso não exista
new_path = '/'.join(['arquivos_mesclados', directory_path.split('/')[1]])
if not os.path.exists(new_path):
os.makedirs(new_path)
Definimos o nome do nosso arquivo destino (único pdf).
output_path = os.path.join(new_path, output_file)
Depois, escrevemos o arquivo unico usando o método write() da classe PdfMerger(). Lembre-se de abrir o arquivo destino como escrita binária (wb).
A função finalizada fica como na imagem a seguir.
Programa principal
Ok, após criarmos todas as nossas funções iremos testar nosso código.
O nome do diretório esta associado a estrutura que tenho no meu projeto com Pycharm. De uma olhada na próxima imagem que você vai entender melhor.
from function import *
# Caminho para o diretório contendo os arquivos PDF
for diretorio in os.listdir('arquivos'):
# Chama a função para mesclar os arquivos PDF no diretório fornecido
merge_pdfs_sorted_by_date('arquivos/'+diretorio)
Após a execução do código a minha estrutura ficou assim:
Para mais projetos com Python
Artigos e tutoriais SR: Projetos com Python em nosso site
Conectando ao MySQL com Python
Projeto para Portifólio: Sua primeira API com Python e MySQL
Principais Bibliotecas Python para Data Science: Manipulação e Visualização
Python: minhas portas TCP e UDP abertas
Playlist do projeto (em construção)
Para quem prefere vídeos, segue nossa playlista do mini projeto.
Juliana Mascarenhas
Data Scientist and Master in Computer Modeling by LNCC.
Computer Engineer
Tutorial Instalar VNC em Linux Ubuntu
O acesso remoto é uma ferramenta indispensável para administradores e usuários que precisam gerenciar servidores…
Tutorial: Instale seu Servidor DNS no Linux com Bind9 Passo a Passo
Nesse tutorial vamos dar todo o passo a passo para que você instale uma configuração…
SSH: Como criar chave pública
Nesse tutorial vamos ensinar a criar e configurar o acesso a um servidor SSH usando…
Socket em Python criando chat UDP
Tutorial para a criação de um chat simples utilizando sockets em UDP em Python 3….
Socket em Python, criando um Chat
Tutorial para a criação de um chat simples utilizando sockets TCP em Python 3. O…
Como usar apt get com proxy
Ao longo dos tempos sempre me deparo nos laboratórios de rede com a necessidade de…