Corrigindo EPUB encoding

2024-02-06 computer books blog

Ontem baixei um livro do libgen.is em EPUB em inglês e ele estava legível mesmo com os sinais bizarros da língua inglesa, como asquelas aspas abre-e-fecha ou aquele travessão que era comum na época da datilografia como dois travessões unidos. No entanto, ao converter para Kindle com o kindlegen.exe tudo isso virou caracteres mais bizarros que um programador reconhece como UTF8 não-reconhecido pela máquina. Coisas como: €™, “, ’, “.

É possível ler, já que todo o resto permanece na confortável zona dos 127 bits da tabela ASCII. Contudo, inglês tem muito apóstrofe e travessão. Às vezes demora algum tempo para decodificar um apóstrofe seguido de um travessão ou vice-versa.

Então resolvi dar uma olhada no arquivo EPUB original. Descompactei e abri o arquivo de introdução do livro, um XHTML dentro da subpasta OEBPS, onde geralmente fica o conteúdo (alguns, como eu em meu blogue, usam a subpasta EPUB, também válida). O arquivo é um XHTML, mas dentro parece HTML, começando assim:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>

No meu blogue cada arquivo XHTML gerado para conversão EPUB utiliza no início uma chave XML:

<?xml version="1.0" encoding="UTF-8"?>

Como eu sei que esses caracteres especiais funcionam no meu Kindle quando leio a conversão de EPUB para MOBI, apenas fiz o necessário: adicionei esta linha no começo de cada XHTML do EPUB original. O resto foi compactar novamente o arquivo EPUB e rodar o kindlegen.exe para este arquivo.

Não é tão simples compactar um EPUB válido. É necessário zipar sem compactação o arquivo mimetype antes de colocar o resto. Em Windows não há um caminho fácil. Como eu gastei algum tempo no conversor do meu blogue, segue abaixo o código em Python para quem precisar:

import os
import zipfile

def zipdir(path, ziph):
  # ziph is zipfile handle
  paths = os.listdir(path)
  for p in paths:
    p = os.path.join(path, p) # Make the path relative
    if os.path.isdir(p): # Recursive case
      zipdir(p, ziph)
    else:
      ziph.write(p) # Write the file to the zipfile

with zipfile.ZipFile('caloni.epub', 'w', compression=zipfile.ZIP_STORED) as zipf:
  zipf.writestr("mimetype", "application/epub+zip")
with zipfile.ZipFile('caloni.epub', 'a', compression=zipfile.ZIP_DEFLATED, compresslevel=5) as zipf:
  zipdir('EPUB', zipf)
  zipdir('META-INF', zipf)

Após isso apenas um kindlegen.exe ebook.epub e tenho um MOBI com caracteres bizarros da língua inglesa funcionando. Para os curiosos de qual livro é este, apenas cito que ele estranhamente não é vendido na Amazon do Brazil. Ou seja, é daqueles ebooks que é mais fácil baixar do que comprar (o que invalida o preço da compra, que, afinal de contas, é para isso que gastamos nosso dinheiro, não?).

[comment] [Tail recursion in loop while]