Open sentry-io[bot] opened 3 years ago
Eu pensei em verificar a extensão antes de tentar executar o unlink
. Cê acha que faz sentido?
Algo mais ou menos assim (nesse arquivo):
has_rar_extension = path.endswith('.rar')
raw = parser.from_file(path)
if not has_rar_extension and not keep_file:
Path(path).unlink()
has_rar_extension = path.endswith('.rar')
if has_rar_extension:
return
raw = parser.from_file(path)
if not keep_file:
Path(path).unlink()
if a_file:
a_file.content = raw["content"]
a_file.save()
return raw["content"]
Ou algo assim, dependendo do que seja retornado pelo parser.from_file
quando o arquivo é RAR.
Na verdade, o melhor seria evitar pular os arquivos .rar
porque eles são maioria nos arquivos compactados - se não forem todos. Perdão pela descrição da issue porque ela não reflete nada disso.
Uma alternativa seria usar alguma outra biblioteca para descompactar os arquivos e aí sim salvá-los de maneira individual. Isso traria alguns problemas, como nós salvando arquivos de corel draw etc. Mas só testando pra saber hehe
Pesquisando sobre .rar e Apache Tika vi isso aqui:
Tika uses the Commons Compress library to support various compression and packaging formats. The CompressorParser class handles parsing of the top level compression formats, then PackageParser class and its subclasses parse the packaging formats and then pass the unpacked document streams to a second parsing stage using the parser instance specified in the parse context. Formats supported include Tar, AR, ARJ, CPIO, Dump, Zip, 7Zip, Gzip, BZip2, XZ, LZMA, Z and Pack200.
Additionally, the RarParser class supports the RAR archive format, which isn't supported by Commons Compress. https://tika.apache.org/1.17/formats.html
Talvez só tenhamos que modificar algo na configuração.
@anapaulagomes tenho algumas dúvidas, cê poderia me ajudar?
tika
no projeto? Quando rodamos o raw = parser.from_file(path)
, qual o conteúdo que esperamos de lá?Procurei um pouco na documentação da tika-python
e não encontrei muita coisa para usar outro parser (o RarParser
). Nem no google achei muitos resultados. Não sei se estou procurando no canto e/ou do jeito certo. Foquei mais na biblioteca, acha que devo voltar o olhar mais na API?
Claro! :)
Show! Daí, quando manipulamos arquivos compactados com o Tika, ele vai saber como manipular todos os tipos de arquivos lá dentro (PDF, corel draw, txt) e nos trazer uma string com todo o conteúdo, confere?
Eu procurei dentro da documentação to tika-python
, procurei no código também, mas não consegui muita coisa ainda, infelizmente. Encontrei uma issue (link) sobre uma dúvidas parecida, porem a resposta apenas sugere a leitura da documentação (de forma bem geral). ): A função from_file
tem um argumento chamado requestOptions
, busquei se havia alguma forma de mudar algo no header, ou em outro canto, para configurar o parser, mas também sem muito sucesso até o momento.
Encontrei o RarParser
na documentação, mas não faço ideia de como fazemos para usa-lo. Tambem achei uma resposta no stackoverflow relacionado a essa questão do RAR5 (link) que comenta sobre "não haver solução disponível para descompactar arquivos RAR5 (no java)".
Estava pensando que se esse for realmente o caso, podíamos tentar descompactar usando algum pacote python (como a rarfile que suporta o RAR5, por exemplo) e mudarmos a função de processamento de parser.from_file(path)
para parser.from_buffer(blob_file)
. Faz sentido essa abordagem? Teríamos que ver qual seria o impacto dessa mudança (tempo e memória principalmente eu acredito).
Show! Daí, quando manipulamos arquivos compactados com o Tika, ele vai saber como manipular todos os tipos de arquivos lá dentro (PDF, corel draw, txt) e nos trazer uma string com todo o conteúdo, confere?
Isso mesmo.
Estava pensando que se esse for realmente o caso, podíamos tentar descompactar usando algum pacote python (como a rarfile que suporta o RAR5, por exemplo) e mudarmos a função de processamento de parser.from_file(path) para parser.from_buffer(blob_file). Faz sentido essa abordagem? Teríamos que ver qual seria o impacto dessa mudança (tempo e memória principalmente eu acredito).
Eu gosto dessa ideia! 🏆 Mas, sim, temos que ver o impacto. Pensando rápido aqui eu acredito que não seria um problema. Obrigada, Geraldo!
Feshow! Vou fazer uns testes/profilings e trago mais informações sobre a mudança.
Fazendo alguns experimentos com o tika
e com bibliotecas que descompactam arquivos RAR no python (como patoolib
e rarfile
) pude perceber alguns pontos (interessantes talvez):
rar
, unrar
e 7z
por exemplo), dai dessa forma não conseguimos pegar o conteúdo de arquivo em memória/buffer; geralmente são comandos para descompactar, listar, ler alguma coisa dentro do arquivo. Acredito que isso também tenha relação do formato RAR
ser proprietário...RAR
para o tika
, não gerou nenhum erro. E quando fui ver os dados retornados, mostra que os parses utilizados, e ele configura sozinho o parser correto: ['org.apache.tika.parser.DefaultParser', 'org.apache.tika.parser.pkg.RarParser']
; não precisamos configurar isso! 🥳 content
) que vem no retorno do tika
depois de processar o arquivo RAR
vem vazio. O parser está correto, não apresenta nenhum erro, mas aparentemente não processa nada. Fiz um teste descompactando os arquivos e enviando apenas um PDF
e o conteúdo foi processado e retornado lindamente.cenário
In [1]: from tika import parser
In [2]: rar_file = '5152pmfscp0272020.rar'
In [3]: pdf_file = '5152pmfscp0272020/teste.pdf'
In [4]: rar_parser = parser.from_file(rar_file)
In [5]: pdf_parser = parser.from_file(pdf_file)
In [6]: pdf_parser['metadata']['X-Parsed-By']
Out[6]:
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pdf.PDFParser']
In [7]: rar_parser['metadata']['X-Parsed-By']
Out[7]:
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pkg.RarParser']
In [8]: len(rar_parser['content'] or '')
Out[8]: 0
In [9]: len(pdf_parser['content'] or '')
Out[9]: 225739
Baixei um arquivo RAR
para testar (link para o arquivo).
Uma outra ideia que tive foi:
Descompactarmos todos os arquivos em um arquivo (temporário), criarmos um novo arquivo compactado (formato ZIP
), enviamos o arquivo pra processar e depois de recebermos o retorno deletarmos tudo! Fiz alguns testes e notei que se enviarmos um arquivo ZIP
, até o parser é diferente, mostrando que pegou o arquivo ZIP
e os PDF
dentro. Tentei criar o arquivo compactado apenas em memória (com a biblioteca zipfile
) mas não é identificado como válido para processar... ):
A ideia de descompactar e compactar pra enviar é pra que todos os arquivos permaneçam juntos para retirarmos um conteúdo único.
In [10]: import zipfile
...:
...: zip_file = zipfile.ZipFile('teste.zip', 'w', zipfile.ZIP_DEFLATED)
...: for file_name in [f'5152pmfscp0272020/teste{num}.pdf' for num in range(1, 6)]:
...: zip_file.write(file_name, file_name)
...:
In [11]: zip_parser = parser.from_file('teste.zip')
In [12]: zip_parser['metadata']['X-Parsed-By']
Out[12]:
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pkg.PackageParser',
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pdf.PDFParser'],
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pdf.PDFParser'],
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pdf.PDFParser'],
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pdf.PDFParser'],
['org.apache.tika.parser.DefaultParser',
'org.apache.tika.parser.pdf.PDFParser']]
In [13]: len(zip_parser['content'] or '')
Out[13]: 574902
Os aquivos de testes foram retirados do mesmo arquivo RAR
.
Encontrei uma abordagem interessante no stackoverflow para converter arquivos RAR
para ZIP
(link).
Podemos usar a biblioteca tempfile
para criar um diretorio temporario com os arquivos descompactados e depois compactarmos para ZIP
e enviarmos para o tika
. O que acham?
>>> import tempfile
# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
... print('created temporary directory', tmpdirname)
>>>
# directory and contents have been removed
Dessa forma, acredito que conseguimos até fazer uma lista de formatos permitidos, ou a serem ignorados, e criamos o arquivo ZIP
apenas com aquilo que queremos que o tika
processe.
Massa, @exageraldo! Por ora, podemos converter em zip e mandar tudo mesmo. Não são muitos os que tem arquivos corel draw e outros. hahaha Obrigada pela investigação! 🥇 Taca lhe pau!
Curiosidade: dos 260 mil arquivos que temos, 500 deles são .rar
. Embora seja um número baixo, as licitações que tem mais arquivos tem mais itens ou são mais caras (pela minha experiência haha).
Essa exceção acontece porque o Tika não consegue extrair o rar 5 (formato proprietário). Temos que pegar a exceção e cancelar o retry nesse caso.
Sentry Issue: MARIA-QUITERIA-4V