Como editores diferentes usam métodos diferentes para "marcar" os PDFs, é necessário comparar sem levar em consideração as marcações.
Você também precisa de um método eficiente para comparar um novo PDF com todos os PDFs já baixados, caso faça o download repetido do mesmo PDF e, por exemplo, esteja marcado com o IP e / ou carimbo de data / hora, conforme sugerido. Você não deseja usar um mecanismo de comparação demorado que compara cada novo PDF com muitos PDFs já baixados
O que você precisa é de um utilitário que retire cada uma das marcações possíveis e gere um hash dos dados restantes. Você precisará manter um mapa de nome de arquivo hash →, que pode estar em um arquivo simples, e se um hash computado já estiver no arquivo, você terá uma duplicata (e a excluirá ou fará o que for necessário) e se o hash ainda não estiver lá, você adiciona o hash e o nome do arquivo. O arquivo seria algo como:
6fcb6969835d2db7742e81267437c432 /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9 /home/anthon/orders/your_order_20150320.pdf
Esse arquivo é negligentemente pequeno comparado aos PDFs originais. Se você possui milhões de PDFs, considere armazenar esses dados em um banco de dados. Por questões de eficiência, convém incluir o tamanho do arquivo e o número de páginas ( pdfinfo | egrep -E '^Pages:' | grep -Eo '[0-9]*'
).
O procedimento acima elimina o problema de remover as marcações e gerar o hash. Se você souber de onde vem o PDF ao chamar a rotina de geração de hash (ou seja, se você fizer os downloads programaticamente), poderá ajustar a geração de hash com base nisso. Mas mesmo sem isso, existem várias possibilidades para geração de hash:
- se os metadados do título e do autor não estiverem vazios e não incluirem sequências não específicas como "Acrobat" ou "PDF", você poderá gerar o hash com base apenas nas informações do autor e do título. Use
pdfinfo -E file.pdf | grep -E '^(Author:)|(Title:) | md5sum
para obter o hash. Você também pode incluir o número de páginas no cálculo do hash (' Pages:
' na pdfinfo
saída).
- se a regra anterior não funcionar e o PDF contiver imagens, extraia as imagens e gere um hash nos dados da imagem combinada. Se as imagens contiverem texto no rodapé ou cabeçalho como "Licenciado para o usuário Joe", retire um número X de linhas na parte superior ou inferior, antes de calcular o hash. Se essas marcações estiverem em algum grande texto em segundo plano acinzentado, é claro que isso não funcionará, a menos que você filtre os pixels que não são totalmente pretos (pelo que você pode usar
imagemagick
). Você pode usar pdfimages
para extrair as informações da imagem em um arquivo temporário.
- se as regras anteriores não funcionarem (porque não há imagens), você pode usar
pdftext
para extrair o texto, filtrar a marcação (se você filtrar um pouco demais, isso não é um problema) e depois gerar o hash com base em aquele.
Além disso, você pode comparar se o tamanho do arquivo antigo encontrado via hash e verificar se está dentro de determinadas margens com o novo arquivo. Compactação e ifferências em seqüências de caracteres (IP / data e hora) só devem resultar em menos de um por cento de diferença.
Se você conhece o método que o editor usa ao determinar o hash, é possível aplicar diretamente o método "correto" acima, mas mesmo sem isso, você pode verificar os metadados e aplicar algumas heurísticas ou determinar o número de imagens em um arquivo e compare isso com o número de páginas (se estiverem próximas, você provavelmente terá um documento que consiste em digitalizações). pdftext
na imagem digitalizada, os PDFs também têm uma saída reconhecível.
Como base para trabalhar, criei um pacote python que está no bitbucket e / ou pode ser instalado no PyPI usando pip install ruamel.pdfdouble
. Isso fornece o pdfdbl
comando que faz a digitalização conforme descrito acima em metadados, imagens extraídas ou texto.
Ele não faz qualquer filtragem de marcas (ainda) , mas o readme descreve quais (dois) métodos para aumentar a não acrescentar que.
O leia-me incluído:
ruamel.pdfdouble
este pacote fornece o pdfdbl
comando:
pdfdbl scan dir1 dir2
Isso percorrerá os diretórios fornecidos como argumento e, para os arquivos PDF encontrados, criará um hash com base em (em ordem):
- metadados se exclusivos
- imagens se o número de imagens
- texto
Isso pressupõe que pdfinfo, pdfimages e pdftotext` do pacote poppler-utils estejam disponíveis.
Um "banco de dados" é construído ~/.config/pdfdbl/pdf.lst
contra o qual outras verificações são testadas.
Removendo marcações
No ruamel/pdfdouble/pdfdouble.py
existem dois métodos que podem ser melhoradas para filtrar marcas no PDF que torná-los menos exclusivo e fazer praticamente os mesmos arquivos para ter diferentes hashes.
Para texto, o método PdfData.filter_for_marking
deve ser estendido para remover e marcações da sequência que é seus argumentos e retornar o resultado.
Para imagens digitalizadas, o método PdfData.process_image_and_update
precisa ser aprimorado, por exemplo, cortando as linhas X inferior e superior da imagem e removendo qualquer texto cinza de fundo, definindo todos os pixels pretos para branco. Essa função precisa atualizar o hash passado usando o .update()
método que passa nos dados filtrados.
Restrições
O "banco de dados" atual não pode manipular caminhos que contêm novas linhas
Atualmente, este utilitário é apenas Python 2.7.
As partes de string em conformidade com o IP podem ser substituídas pelo re
módulo do Python :
import re
IPre = re.compile("(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}"
"([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")
x = IPre.sub(' ', 'abcd 132.234.0.2 ghi')
assert x == 'abcd ghi'