helio.loureiro.eng.br
  • Home
  • Unix
  • Linux
  • Blog
  • Python
  • Programação
  • Tudo
  • Suécia
  1. You are here:  
  2. Home
  3. Python
  4. UnicodeEncodeError: 'ascii' codec can't encode character

Os artigos mais lidos de 2025

  • Configurando o grafana alloy pra monitorar VMs
  • Configurando traefik com ssh
  • Configurando o teclado Keychron C3 no Linux
  • Parâmetros de compilação pra Go!
  • Acessos de robôs nos logs web

PyCon Brasil 2013

Details
Written by: Helio Loureiro
Category: Python
Published: August 06, 2013
Hits: 8831

Esse enviei 2 apresentações pra Python Brasil.  Uma falando sobre python-twitter (e como faço pra enviar os #FF de sexta-feira) e outra pra falar sobre python em telecomunicações.

Não tenho nada escrito ainda, e vou aguardar a confirmação do trabalho pra começar.  Se der certo, estarei em Brasília no início de outubro :-)

Adicionando controle automático de acesso ao wifi

Details
Written by: Helio Loureiro
Category: Python
Published: September 22, 2012
Hits: 11183

Fonte: http://www.tiagodoria.ig.com.br/2007/08/28/edelman-prepara-estudo-inedito-sobre-blog-no-brasil/Para quem tem filho adolescente, sabe que as traquitanas tecnológicas tornaram a vida um inferno quando o assunto é estudar.  Controlar o acesso ao computador é fácil, criando regras de bloqueio após certos horários estabelecidos, ou mesmo permissão e filtragem de acessos à sites baseados em URL e squid.

Mas com a chegadas dos dispositivos móveis, como telefones Android e tablets, a coisa não ficou tão fácil.

Restou a opção de bloquear o acesso pelo MAC address nos horários de estudo (que em geral são transformados em horários de soneca durante a tarde ou televisão).

Então fiz um pequeno script em python que bloqueia os MACs já cadastrados, tanto do tablet quanto do smartphone, e libera nos horários em que o computador desktop também está liberado.  Com certeza isso não resolve o problema, mas com adolescentes, em geral, quase nada resolve.

O programa funciona com meu roteador wifi, um WR3G01, que comprei no Dealextreme (mais informações aqui).  É um roteador wireless que se diz compatível com DD-WRT, mas que pra isso exige soldar os contatos da conexão serial na placa e carregar o firmware por tftp (era mais fácil dizer que não suporta então).

 

O programa segue:


#! /usr/bin/python
import re, urllib2
from base64 import encodestring
from sys import argv

MACS = [ "94:63:AA:BB:CC:DD", "74:E1:AA:BB:CC:DD" ]
login = "admin"
password = "admin"
server = "192.168.0.1"
port = 80
URI = "/apply.cgi"

TAG =""
for mac in MACS:
  mac = re.sub(":",'%3A', mac)
  TAG += mac + '%3B'

def Usage():
  print "Use: %s {block|allow}" % argv[0]
  exit(1)


if (len(argv) < 2):
  Usage()
elif (not re.search("allow|block",argv[1])):
  Usage()
  
msg_body = "submit_button=wlan_access&" + \
  "change_action=&" + \
  "action=Apply&" + \
  "AccessControlList0=" + TAG + "&"

if (argv[1] == "allow"):
  msg_body += "AccessPolicy0=0&"
elif (argv[1] == "block"):
  msg_body += "AccessPolicy0=2&"
msg_body += "mac=&mac=&mac=&mac=&mac=&mac=&"
if (argv[1] == "allow"):
  msg_body += "selectMAC=1"
elif (argv[1] == "block"):
  msg_body += " selectMAC=3"

http_pass = encodestring(login + ":" + password)
url = "http://" + server + ":" + str(port) + URI

my_headers = {
  'User-Agent' : 'Python Client/1.0/1.0',
  'Authorization' : 'Basic ' + http_pass,
  'Content-Type' : 'application/x-www-form-urlencoded'
}

req = urllib2.Request(
  url,
  headers = my_headers,
  data = msg_body
)

print "Sending: %s" % argv[1]
resp = urllib2.urlopen(req)

Python em telecom em 7 minutos

Details
Written by: Helio Loureiro
Category: Python
Published: May 29, 2012
Hits: 8400

Essa é uma apresentação que fiz na iMasters em abril último, no evento 7Masters sobre python. 

Não é um curso de python, nem nada próximo disso, mas apenas uma visão de que telecom é na verdade um grande TI, com aplicações que todos nós já conhecemos bem.

7_minutes_python_telecom.swf

 

Era uma apresentação que deveria levar 7 minutos.  Gastei 20.

UPDATE: 2021-12-23 troquei o arquivo embedded de flash pra um gif animado uma vez que nenhum browser sério ainda suporta swf.

 

UnicodeEncodeError: 'ascii' codec can't encode character

Details
Written by: Helio Loureiro
Category: Python
Published: April 13, 2012
Hits: 9697

Não é de hoje que me deparo com esses erros de unicode em python.

Em algumas funções que uso, principalmente as que lêem de timeline de redes sociais, tenho problemas com caracteres.  Dessa vez eu estava fazendo um programa que lê a timeline da rede social da empresa, que é baseada num produto lixo da Microsoft, o ShamePoint, digo, SharePoint, que publica a API de mensagens no formato RSS.  A função é pra gerar um gráfico de mensagens a cada 5 minutos para verificar o andamento da rede social (que passou do momento de hype).  Então como o ShamePoint é limitado em suas funções, resolvi fazer um "tracking" de posts através de uma função com um hash MD5 da mensagem postada.  

A idéia não é muito complexa, mas eis que fazendo o hash eu achei um:


helio@shibboleet:pynet$ ./mynet_tag_posts.py
Getting posts
Reading output and rss
Traceback (most recent call last):
  File "./mynet_tag_posts.py", line 106, in 
    main()
  File "./mynet_tag_posts.py", line 103, in main
    RSS = RSS_parser(XML)
  File "./mynet_tag_posts.py", line 60, in RSS_parser
    key = md5sum(rss.summary_detail.value)
  File "./mynet_tag_posts.py", line 19, in md5sum
    m.update(msg)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xc5' in position 96: ordinal not in range(128)

E a função de hash MD5, a md5sum(), é super simples:


def md5sum(msg):
  m = hashlib.md5()
  m.update(msg)
  return m.hexdigest()

Só que mensagens com caracteres não ASCII, como em português ou suéco, simplesmente matam o processamento do MD5.

Em outros scripts eu contornei isso fazendo uma análise por caractere e substituindo todo aquele que tivesse valor maior que 128 por seu semelhante não acentuado na tabela ASCII.   Trabalho tosco, mas funcional.

Dessa vez resolvi procurar como corrigir isso.  E pra sempre.  Procurei na documentação do python sobre tratamento de unicode.

E não é que achei a solução do jeito mais simples e pythonista possível?  Basta forçar um atributo de formato de caractere no texto, como texto.encode(formato).  No caso, mudei a função para essa abaixo, usando formato de caracteres "utf-8":


def md5sum(msg):
  m = hashlib.md5()
  msg = msg.encode('utf-8')
  m.update(msg)
  return m.hexdigest()

E o problema foi resolvido.  Sem mais chororo de formatos iso-8859-1 e utf-8.  

Limpando os SPAMs do eri.cx

Details
Written by: Helio Loureiro
Category: Python
Published: April 15, 2011
Hits: 8448

Ultimamente, monitorando meu encurtador eri.cx, notei que o mesmo estava recebendo muitos links sem nenhum clique.  Olhando mais de perto pude ver que os mesmos eram relacionados à SPAM/vírus.  Alguns robôs de Internet, ou mesmo máquinas zumbis, que adicionam esses links suspeitos.

Um dos agressores foi claramente o IP 213.5.66.88.   Resolvi o problema adicionando-o em duas regras de firewall bem simples:


iptables -A INPUT -p tcp --dport 80 -s 213.5.66.88 -j LOG
iptables -A INPUT -p tcp --dport 80 -s 213.5.66.88 -j REJECT

Criei uma tabela chamada quarantine e migrei as entradas do banco para lá, manualmente.  E também notifiquei os administradores do site sobre o ocorrido, enviando mail para abuse@site e security@site.

Achei que a solução era perfeita e que tinha resolvido meus problemas.  Essa semana dei uma  olhada novamente na base do encurtador.  De 900 links inseridos, uns 350 eram desse tipo (malditos SPAMMERS!).

Chorei minhas mágoas no Twitter, bem no estilo "reclamar no Twitter muito", e recebi algumas sugestões para evitar esses ataques.  Mesmo meu guru mental para idéias técno-copiadas, Eduardo Maçan, que administra o encurtador miud.in -- do qual chupinhei várias coisas, sugeriu uma verificação do encurtador via web através do refereer antes de encurtar qualquer link.

Pensei em fazer isso, mas tornaria impossível notificar os administradores dos sites afetados que suas máquinas estão comprometidas, e fora o problema de performance que poderia ocorrer ainda mais que o hosting que contratei tem somente 64 MB de RAM e CPU compartilhada num ambiente Xen.  Então resolvi mudar a abordagem e simplesmente deixar as máquinas zumbis adicionarem as URLs "do mal".  Mas uma vez por dia eu rodo um programa em Python que faz a busca de padrões desses vírus/scammers, move pra base do quarentine (assim ninguém clicará nos mesmos) mantendo as mesmas entradas, e comunica ao mails abuse@domínio e security@domínio sobre o ataque.

Então segue o script que fiz para esse fim.


#! /usr/bin/python
# -*- coding: utf-8 -*-
# $Id:$ 

# COPYRIGHT
#
#    Copyright (c) 2011 by Helio A. L. Loureiro
#
#    Permission to use, copy, modify, distribute, and sell this software
#    for any purpose is hereby granted without fee, provided that the above
#    copyright notice appear in all copies and that both that copyright
#    notice and this permission notice appear in supporting documentation.
#    No representations are made about the suitability of this software for
#    any purpose. It is provided "as is" without express or implied
#    warranty.

### main code
from os import popen
from re import sub, search
import smtplib
from time import ctime,strftime


mysqldb = "eri.cx"
mysqluser = "eri.cx"
mysqlpasswd = "xc.ire"
log_dir = "/var/log"

# Enviando mensagens
def Log(msg):
	log_file = log_dir + "/report-sql-spam-" + \
		strftime("%Y-%m") + ".log"
	msg = msg.rstrip("\n")
	msg = "[ " + ctime() + " ] " + msg + "\n"
	log = open(log_file, "a")
	log.write(msg)
	log.close()

# Formatando o texto do mysql
def GenSQLCommand(sql):
	cmd = "mysql -u %s -p\'%s\' %s << EOF" % (mysqluser, mysqlpasswd, mysqldb)
	cmd = cmd + "\n" + sql + "\n" + "EOF\n"
	
	return cmd
	
def RetrieveMySQL():
	sql = """SELECT 
	yourls_url.keyword,
	yourls_url.url, 
	yourls_url.title,
	yourls_url.timestamp,
	yourls_url.ip,
	yourls_url.clicks
	FROM yourls_url WHERE  
	yourls_url.title like '%dingo.ucsf.edu%' OR
	yourls_url.title like '%cssa.grad.wustl.edu%' OR
	yourls_url.title like '%wiki.usfca.edu%' OR
	yourls_url.title like '%pantherfile.uwm.edu%' OR
	yourls_url.title like '%csci.marietta.edu%' OR
	yourls_url.title like '%webfiles.uci.edu%' OR
	yourls_url.title like '%Ultram %' OR
	yourls_url.title like '%Cialis%' OR
	yourls_url.title like '%Tramadol%' OR
	yourls_url.title like '%xanax%' OR
	yourls_url.title like '%viagra%' ORDER BY yourls_url.keyword;
	"""
	cmd = GenSQLCommand(sql)
	
	sql_result = popen(cmd).readlines()
	sql_result = sql_result[1:]

	return sql_result
	
def InsertQuarantine(db_lines):
	sql = """INSERT INTO yourls_quarantine 
	(keyword, url, title,timestamp,ip,clicks) VALUES """
	for e in db_lines:
		sql = sql + "\n( "
		e = e.rstrip("\n")
		for d in e.split("\t"):
			sql = sql + "\'" + d + "\', "
		sql = sql[:-2] + " ),"
	sql = sql[:-1]
	cmd = GenSQLCommand(sql)
	popen(cmd).read()
	
def DeleteEntries(keywords):
	sql = """DELETE FROM yourls_url USING yourls_url WHERE """ 
	sql = sql + "keyword = \"%s\"" % keywords[0]
	for k in range(1, len(keywords)):
		sql = sql + "OR keyword = \"%s\"" % keywords[k]
		
	cmd = GenSQLCommand(sql)
	popen(cmd).read()
	
def GetDomain(url):
	url = sub("^http://", "", url)
	url = sub("^https://", "", url)
	url = sub("/.*", "", url)
	
	return url

def SendMail(rcpts, msg):
	fromaddr = "helio" + "@" + "domain.com"
	mail = smtplib.SMTP('localhost')
	mail.sendmail(fromaddr, rcpts, msg)
	mail.quit()

def Main():
	spam_list = RetrieveMySQL()
	
	ATTACKED = {}
	KEYWORDS = []
	for spam in spam_list:
		Log(sub("\t", ",", spam))
		keyword, url, title, timestamp, ip, clicks = spam.split("\t")
		domain = GetDomain(url)
		KEYWORDS.append(keyword)
		try:
			ATTACKED[domain].append(spam)
		except KeyError:
			ATTACKED[domain] = [spam]
			
	for poor_soul in ATTACKED:
		rcpts = ["abuse@" + poor_soul, 
		"root@" + poor_soul,
		"security@" + poor_soul]
		msg = """From: Helio Loureiro <""" + "helio" + "@" + "domain.com" + """>
To: abuse@%s, root@%s, security@%s
Subject: Service abused from your domain

Hi,
		
I'm the sysadmin from domain eri.cx, a little poor shortener.
Recently I noticed some attacks (SPAM url shorteneds) coming from
your site.

Here follows the logs:

#timestamp|ip|title|url
""" % (poor_soul, poor_soul, poor_soul)
		for spam in ATTACKED[poor_soul]:
			keyword, url, title, timestamp, ip, clicks = spam.split("\t")
			msg = msg + "%s|%s|%s|%s\n" % (timestamp, ip, title, url)
		#print poor_soul, "=>", ATTACKED[poor_soul]
		
		msg = msg + """
It seems your server was compromised.  So please take actions accordingly.

This is an automatic mail report.  My apologizes if it sent unwanted 
information.

Best Regards,
Helio Loureiro
http://eri.cx
"""
		#print msg
		SendMail(rcpts, msg)
		InsertQuarantine(spam_list)
		DeleteEntries(KEYWORDS)

if __name__ == '__main__':
	Log("== Starting... == ")
	Main()
	Log("## Finishing... ## ")
  1. Enviando IP por mail com Python
  2. Escrevendo uma aplicação com python-twitter (parte 3 - final)
  3. Escrevendo uma aplicação com python-twitter (parte 2)
  4. Escrevendo uma aplicação com python-twitter (parte 1)

Page 7 of 9

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Estatísticas

  • Users 2
  • Articles 486
  • Articles View Hits 3556247

Imagem aleatória