Instalando/atualizando a lxml no Windows 8.1 para Python 2.7

Hoje, ao tentar atualizar a biblioteca lxml pelo pip, obtive um erro de compilação e não consegui atualizar.

Pesquisando, descobri que podia instalar/atualizar a lxml para a versão mais atual utilizando um arquivo no formato wheel (.whl) disponibilizado em um repositório nã0-oficial de pacotes de extensão Python para Windows.

No repositório, baixei a versão lxml-3.5.0-cp27-none-win32.whl (versão 3.5 para Python 2.7). No diretório onde baixei o arquivo executei o comando pip install lxml-3.5.0-cp27-none-win32.whl. E pronto, problema resolvido :)

Publicado em Soluções | Marcado com , | Deixe um comentário

Reduzindo o tamanho de um arquivo PDF com Ghostscript

Dia destes, no trabalho, me solicitaram a redução ou divisão de um arquivo PDF para o tamanho máximo de 10 MB.

Como já utilizei o Ghostscript para desbloquear arquivos PDF, procurei uma solução em que pudesse utilizá-lo.

É possível, utilizando-se o comando abaixo (que deve ser digitado em uma linha só):

gswin64 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite
-dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen
-sOutputFile=PDF_REDUZIDO.pdf PDF_ORIGINAL.pdf

onde:
gswin64 – comando do Ghostscript no Windows 64 bits;
-dNOPAUSE – desabilita o prompt ao final de cada página processada;
-dBATCH – habilita o processamento em lote;
-sDEVICE=pdfwrite – determina o dispositivo de saída; o pdfwrite é para a geração do PDF;
-dCompatibilityLevel=1.4 – determina o nível de compatibilidade; aqui foi usado o nívl 1.4, compatível com o Adobe Reader 5 ou superior;
-dPDFSETTINGS=/screen – qualidade do PDF gerado (aqui fica com a qualidade de imagem de 72 dpi, para visualização em tela)
-sOutputFile=PDF_REDUZIDO.pdf – especifica o nome do arquivo a ser gerado
PDF_ORIGINAL.pdf – nome do PDF original que se deseja reduzir

Em meu caso, o arquivo original que tinha 21,1 MB ficou com 9,60 MB após a redução.

Fontes:
http://www.vivaolinux.com.br/dica/GhostScript-Reduzindo-o-tamanho-de-arquivos-PDF-pelo-terminal
http://milan.kupcevic.net/ghostscript-ps-pdf/
http://www.peteryu.ca/tutorials/publishing/pdf_manipulation_tips

Publicado em Soluções | Marcado com , | Deixe um comentário

Código Morse em Python

Recentemente, em seu twitter, o escritor Eduardo Spohr escreveu duas mensagens em código Morse. O que me levou a escrever uma classe em Python que codificasse e decodificasse este código.

O código Morse é um sistema binário desenvolvido em 1835 por Samuel Finley Breese Morse para representar as letras do alfabeto bem como os numerais. Utiliza sons curtos e longos ou pontos e traços para transmissão de mensagens.

Código Morse Internacional

CÓDIGO

O código em Python foi implementado conforme a tabela acima. O código morse para ser decodificado deve ter espaços em brancos para separar cada código. Código salvo no arquivo morse.py.

class Morse(object):
    def __init__(self):
        self.morse_code = {
            'A': '.-', 'B': '-...',
            'C': '-.-.', 'D': '-..',
            'E': '.', 'F': '..-.',
            'G': '--.', 'H': '....',
            'I': '..', 'J': '.---',
            'K': '-.-', 'L': '.-..',
            'M': '--', 'N': '-.',
            'O': '---', 'P': '.--.',
            'Q': '--.-', 'R': '.-.',
            'S': '...', 'T': '-',
            'U': '..-', 'V': '...-',
            'W': '.--', 'X': '-..-',
            'Y': '-.--', 'Z': '--..',
            '0': '-----', '1': '.----',
            '2': '..---', '3': '...--',
            '4': '....-', '5': '.....',
            '6': '-....', '7': '--...',
            '8': '---..', '9': '----.'
        }

    def decode(self, morsecode):
        ''' Decodifica codigo morse '''
        code = morsecode.split(' ')
        text = ''
        for item in code:
            for key, value in self.morse_code.iteritems():
                if item == value:
                    text += key
                    break
        return text

    def encode(self, plaintext):
        ''' Codifica em codigo morse '''
        code = ''
        for char in plaintext.upper():
            if char in self.morse_code.keys():
                code += self.morse_code[char] + ' '
        return code

TESTE

Com o módulo abaixo podemos testar a classe Morse.

# -*- coding: utf-8 -*-
from morse import Morse
import sys

versao = sys.version_info[0]

if versao == 2:
	leitura = raw_input
elif versao == 3:
	leitura = input

txt_in = leitura('Texto a ser codificado: ')

morse = Morse()
codigo = morse.encode(txt_in)
print
print('Codigo Morse: {0}'.format(codigo))
print(' Texto plano: {0}'.format(morse.decode(codigo)))

Executando, temos como saída:

Texto a ser codificado: a reuniao sera as 10h

Codigo Morse: .- .-. . ..- -. .. .- --- ... . .-. .- .- ... .---- ----- ....
 Texto plano: AREUNIAOSERAAS10H

Fontes:
https://en.wikipedia.org/wiki/Morse_code

Publicado em Criptografia | Marcado com , | Deixe um comentário

Cifras criptográficas em repositório no GitHub

Bom, depois de tanto tempo ausente, resolvi postar algo útil :)

Meus últimos posts foram de cifras criptográficas implementadas na linguagem Python. Para facilitar, resolvi disponibilizar os códigos-fontes num repositório no GitHub: https://github.com/fabmedeiros.

Assim, todas as cifras que eu for implementando serão disponibilizadas aqui no blog e lá.

Publicado em Criptografia | Marcado com | Deixe um comentário

Aviso InsecurePlatformWarning ao verificar a lista de pacotes no pip

Hoje fui verificar se havia algum pacote do pip que necessitasse de atualização. Só que ao executar o comando abaixo:

pip list -o

recebi a seguinte mensagem de aviso:

C:\Python27\lib\site-packages\pip\_vendor\requests\packages\urllib3\util\ssl_.py:79: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning

De acordo com o link no aviso[1] versões do Python abaixo da 2.7.9 (estou usando a 2.7.8) têm alguma restrição ao módulo ssl e a recomendação é a atualização do Python :) .

Feito a atualização tudo volta ao normal.

[1] https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning

Publicado em Soluções | Marcado com , | Deixe um comentário

Instalando a matplotlib para Python 2.7 no Windows 8.1

Estes dias resolvi criar um gráfico com dados de um arquivo texto. Como gosto de programar em Python, procurei por um módulo/biblioteca que me permitisse a criação destes gráficos o mais simples possível. Encontrei a matplotlib.

Resumindo, a matplotlib é uma biblioteca que permite a criação de gráficos em 2D. Para sua instalação faz-se necessária a utilização da biblioteca NumPy (que é uma biblioteca para computação científica utilizando Python).

Ambas podem ser instaladas pelo pip. Para instalar a matplotlib basta digitar o comando (no prompt):

pip install matplotlib

Só que no final da instalação, recebo o erro abaixo:

error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat
Get it from http://aka.ms/vcpython27

----------------------------------------
Command "C:\Python27\python.exe -c "import setuptools, tokenize;__file__=
\\users\\omega\\appdata\\local\\temp\\pip-build-sk3bzn\\numpy\\setup.py';exec
mpile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'),
file__, 'exec'))" install --record c:\users\omega\appdata\local\temp\pip-judm
record\install-record.txt --single-version-externally-managed --compile" fail
with error code 1 in c:\users\omega\appdata\local\temp\pip-build-sk3bzn\numpy

Pesquisando, descobri que o Python quer compilar a biblioteca NumPy, mas não encontra o compilador para tal (Microsoft Visual C++ 9). Aí entra a Microsoft :)

Ela criou um compilador específico para o Python 2.7 o Microsoft Visual C++ for Python 2.7. No site clicando-se no botão Download, baixamos o arquivo VCForPython27.msi. Após baixado basta rodar o arquivo. O instalador segue o processo padrão de outros instaladores para programas Windows. Após o processo de instalação, digitamos novamente o comando para instalar o matplotlib:

pip install matplotlib

Feito isto, o processo de instalação segue normal.

P.S.: esta mesma dica foi feita num computador rodando Windows 7 64

Publicado em Soluções | Marcado com , , | 1 Comentário

Criptografia: cifra de Vigenère em Python

A cifra de Vigenère (atribuída equivocadamente a Blaise de Vigenère) foi descrita primeiramente pelo italiano Giovan Battista Bellaso, em 1553, em sua obra La cifra del. Sig. Giovan Batista Bellaso e por muito tempo foi considerada como le chiffre indéchiffrable (a cifra indecifrável) quando, em meados do século XIX,  Charles Babbage e Friedrich Kasiki encontraram um método de resolvê-la.

É uma cifra polialfabética e seu funcionamento vai lembrar um pouco a cifra de Trithemius, só que a cifra de Vigenère utiliza uma chave para cifrar uma mensagem, e um pouco da cifra de Della Porta, só que para cada letra da chave corresponde um alfabeto diferente.

    A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
--------------------------------------------------------
A - A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
B - B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A
C - C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B
D - D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C
E - E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D
F - F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E
G - G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F
H - H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G
I - I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H
J - J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I
K - K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J
L - L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K
M - M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L
N - N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M
O - O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N
P - P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O
Q - Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P
R - R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q
S - S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R
T - T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S
U - U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T
V - V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U
W - W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V
X - X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W
Y - Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X
Z - Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y

O processo de cifragem utiliza uma chave que se não tiver o mesmo tamanho do texto a ser cifrado deve ser repetida até que o texto plano e a chave tenham o mesmo tamanho. Por exemplo, tomemos como texto plano há um espião entre nós e a chave hoplita:

texto plano - haumespiaoentrenos
      chave - hoplita

Veja que o texto plano tem 18 letras e a chave tem 7 letras, assim, vamos repetir a chave hoplita até chegarmos ao tamanho de 18 letras. Ficando assim:

texto plano - haumespiaoentrenos
      chave - hoplitahoplitahopl

Agora com a chave de tamanho igual ao texto plano começamos o processo de cifragem. Utilizando a primeira letra do texto plano (h) como coluna e a primeira letra da chave (h) como linha, encontramos na interseção a letra O, que é a letra cifrada de h com o alfabeto h.

  texto plano - haumespiaoentrenos
        chave - hoplitahoplitahopl
texto cifrado - O

A segunda letra do texto plano (a) utilizará o alfabeto da segunda letra da cifra (o), resultando na letra O novamente.

  texto plano - haumespiaoentrenos
        chave - hoplitahoplitahopl
texto cifrado - OO

O processo se repetirá para todas as letras do texto plano.

  texto plano - haumespiaoentrenos
        chave - hoplitahoplitahopl
texto cifrado - OOJXMLPPODPVMRLBDD

Neste nosso exemplo o texto plano há um espião entre nós será cifrado como OOJXMLPPODPVMRLBDD.

CÓDIGOS

Alterei a classe base Cipher (criada no post da cifra de Della Porta) e a salvei no arquivo cipher.py.

# -*- coding: utf-8 -*-
class Cipher(object):
    """ Classe base para as cifras classicas """
    def format_str(self, text):
        '''
        Retorna text sem espacos e em maiusculas
        '''
        return text.replace(' ', '').upper()

    def shift_alphabet(self, alphabet, shift):
        '''
        Retorna alphabet com deslocamento de valor shift
        '''
        return alphabet[shift:] + alphabet[:shift]

A classe Vigenere é a responsável pela cifragem e decifragem e está salva no arquivo vigenere.py.

# -*- coding: utf-8 -*-
from cipher import Cipher

class Vigenere(Cipher):
    """ Cifra de Vigenere """
    def __init__(self):
        self.plain = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

    def repeat_password(self, password, text):
        '''
        Repete a password ate o tamanho de text
        '''
        if len(password) < len(text):
            new_pass = password * (len(text)/len(password))
            if len(new_pass):
                new_pass += password[:len(new_pass)]
            return new_pass.upper()
        return password.upper()

    def encrypt(self, plaintext, password, decrypt=False):
        '''
        Cifra plaintext com a cifra de Vigenere
        Decifra se decrypt for True
        '''
        password = self.repeat_password(password, plaintext)
        plaintext = self.format_str(plaintext)
        textout = ''
        for idx, char in enumerate(plaintext.upper()):
            # indice da letra da cifra
            idx_key = self.plain.find(password[idx])
            # gera alfabeto cifrado
            c_alphabet = self.shift_alphabet(self.plain, idx_key)

            if decrypt:
                idx_p = c_alphabet.find(char)
                textout += self.plain[idx_p]
            else:
                idx_p = self.plain.find(char)
                textout += c_alphabet[idx_p]

        return textout

    def decrypt(self, ciphertext, password):
        '''
        Decifra ciphertext
        '''
        return self.encrypt(ciphertext, password, True)

TESTES

Para teste criamos o arquivo teste_vigenere.py que chama a classe Vigenere.

# -*- coding: utf-8 -*-
from vigenere import Vigenere
import sys

versao = sys.version_info[0]

if versao == 2:
	leitura = raw_input
elif versao == 3:
	leitura = input

txt_in = leitura('Texto a ser cifrado: ')
password = leitura('Senha: ')

cifra = Vigenere()
txt_cifrado = cifra.encrypt(txt_in, password)
print
print('Texto cifrado: {0}'.format(txt_cifrado))
print('  Texto plano: {0}'.format(cifra.decrypt(txt_cifrado, password)))

Vamos testar a cifra com a frase no dia dez o ataque sera pelo norte e senha armagedom.

Texto a ser cifrado: no dia dez o ataque sera pelo norte
Senha: armagedom

Texto cifrado: NFPIGHHNAAKMQAIVSDAGQLURRFFE
  Texto plano: NODIADEZOATAQUESERAPELONORTE

FONTES

http://pt.wikipedia.org/wiki/Cifra_de_Vigenère
http://en.wikipedia.org/wiki/Vigenère_cipher
http://www.numaboa.com.br/criptografia/cifras/substituicoes/polialfabeticas/506-vigenere

Publicado em Criptografia | Marcado com , | Deixe um comentário