Python: UnicodeEncodeError: ‘ascii’ codec can’t encode character u’\u20ac’

Chiunque abbia fatto un minimo di parsing HTML tramite Python, ha incontrato almeno una volta questo fatidico errore (almeno lo spero, altrimenti sono l’unico pseudo smanettone ad averlo avuto 😛 ), soprattutto se il parsing e’ stato effettuato su pagine web in cui la valuta e’ l’Euro, dato che \u20ac rappresenta il simbolo “€” (dannato Euro, anche nel mondo dell’informatica ci da’ problemi).

Il problema deriva avviene quando Python cerca di codificare il simbolo  € con un carattere ASCII.

Codifica?? Uhm?? se sei confuso come me… continua a leggere 😀

Prima di continuare facciamo un piccolo ricapitolazione di “Fondamento di Informatica”…la cosa piu’ importante da sapere e’ che: l’oggetto str in Python memorizza il suo valore come bytes, cioe’ con una sequenza di 8-bit, a.k.a string. Per questo motivo ogni carattere ASCII viene codificato in 8-bit, questo vuol dire che abbiamo a disposizione 0-255 rappresentazioni diverse… ma questo non e’ sufficiente per rappresentare i caratteri Russi, Arabi, Giapponessi… ed il nostro famoso simbolo dell’euro.

Per superare questa limitazione, Python usa unicode che memorizza il carattere con 16-bit o 32-bit dandoci la possibilita’ di rappresentare qualsiasi simbolo in qualsiasi linguaggio.

Voi direste.. Evviva! basta usare l’unicode e risolvo il problema, giusto? NO, non puoi…. ci mancherebbe che il mondo dell’informatica sia cosi’ logico e “clean” 😀

In particolare, non si puo scrivere su un file usando l’unicode, perche’ il file vuole una stringa che sia rappresentata da 8-bit. Dato che Python e’ molto “smart” cerchera’ in automatico di codificare/uniformare il carattere in unicode per la scrittura su file (o qualsiasi altro stream, come la shell), ma ahime’ c’e’ un problema… vediamo meglio con un esempio.

[sourcecode language=”python”]
>>> price_info = u’the price is \u20ac 5′
>>> type(price_info)
<type ‘unicode’>
>>> f = open(‘priceinfo.txt’,’wb’)
>>> f.write(price_info)
Traceback (most recent call last):
File "", line 1, in ?
UnicodeEncodeError: ‘ascii’ codec can’t encode character u’\u20ac’ in position 9: ordinal not in range(128)
>>>
[/sourcecode]

What happened?? Quando Python cerca di scrivere nel file “the price is € 5”, egli cerca di trasformare il valore unicode ‘\u20ac‘ in un carattere ASCII ad 8-bit… ma prima abbiamo detto che ASCII non contiene il carattere in questione… per cui… mi stai seguendo?? 😀

La soluzione e’ semplice (dopo che ho passato almeno una nottata su stackoverflow 😛 ):

[sourcecode language=”python”]
>>> price_info_enc = price_info.encode(‘utf-8’) # >> price_info_enc
‘it costs \xe2\x82\xac 5’
>>> type(price_info_enc)
<type ‘str’>
>>> f.write(price_info_enc)
>>> f.close()
[/sourcecode]

Semplice!! abbiamo codificato l’unicode tramite ‘utf-8’, il quale usa una sequenza di 3 caratteri ‘\xe2\x82\xac‘ per rappresentare il simbolo dell’Euro , in questo modo possiamo passare facilmente da ‘utf-8′ ad ASCII.

Ovviamente nel caso volessimo leggere il simbolo al contrario ( cioe’ vedere sullo schermo il simbolo dell’euro) dovremmo procedere con la decodifica dei tre caratteri in ‘utf-8′ e poi effettuare il print 😉

Ma c’e’ davvero gente che legge i miei post??? Mmmm ne dubito… ma come sempre, questo post mi servira’ da qui ad una settimana, visto che la mia memoria e’ scarsa e mi capitera’ di nuovo di imbattermi in questo problema… spero almeno di ricordarmi di aver scritto qualcosa sull’argomento 😛

Bash: Script download automatico con MlDonkey dei link ed2k dal Forum dduniverse.net

Vi assumete tutte le responsabilità nell’uso illegale dello script 😛

Stamattina non avendo nulla di meglio da fare, o meglio, cercando una “seria” alternativa allo studio… mi sono messo a girare per il forum dduniverse.net in cerca di qualche videolezione di UniNettuno sui Sistemi Operativi 😀

Dopo una breve ricerca riesco a trovare la pagina ed inizio a copiare-incollare i link ed2k… arrivato al link 5/29 mi chiedo, ma come posso automatizzare il download dei link ed2k sul mio server MLDoneky ? (uso Safari per la navigazione e non posso usare lo script messo a disposizione nella pagina del forum)

Eccovi la risposta che mi sono dato 😀

download_link_mldonkey.sh
[sourcecode language=”bash”]

#!/bin/sh

#############################
# Author #
# Flavio Pace #
# www.vitadastudente.it #
# #
############################
function usage(){
echo “Usage $0 URL_Links IP_Server_MlDoneky –> to login and download”
echo “Example :”
echo “$ sh download_link_mldonkey.sh http://dduniverse.net/ita/viewtopic.php?p=5691388 localhost ”
}
PHPBB_URL=http://dduniverse.net/ita/
PHPBB_TARGET_URL=$1
USER=flavio_user
PASS=flavio_pass
USER_MLDONEKY=admin
PASS_MLDONKEY=admin
MLDONKEY_IP=$2
MLDONKEY_PORT=4000

#————————— login —————————
if [ $# -eq 2 ] ; then

wget –save-cookies=./session-cookies-$USER $PHPBB_URL/ucp.php?mode=login -O – 1> /dev/null 2> /dev/null

SID=`cat ./session-cookies-$USER | grep _sid | cut -d$’\011′ -f7`

echo “Login $USER –> $PHPBB_URL SID=$SID”

wget –save-cookies=./session-cookies-$USER \
–post-data=”username=$USER&password=$PASS&redirect=index.php&sid=$SID&login=Login” \
$PHPBB_URL/ucp.php?mode=login –referer=”$PHPBB_URL/ucp.php?mode=login” \
-O – > /dev/null

echo ” Download Page with Link ”
wget –load-cookies ./session-cookies-$USER $PHPBB_TARGET_URL -O link.txt

echo ” Running Parsing on file ”
grep -o ‘ed2k://[^”]*’ link.txt | grep -v ‘;’ > link_par.txt

echo ” Connect Mldoneky Server”
(echo auth $USER_MLDONEKY $PASS_MLDONEKY;echo dllinks $PWD/link_par.txt; echo vd; echo q) | nc $MLDONKEY_IP $MLDONKEY_PORT

else

usage
fi

[/sourcecode]

 

Lo script è stato scritto per l’uso con il forum phpBB dduniverse.net, ma nulla vi vieta di modificarlo a vostra piacimento per qualsiasi altro forum e/o sito web.

I parametri USER e PASS sono relativi all’accesso a dduniverse.net

I parametri  USER_MLDONKEY e PASS_MLDONEY sono relativi all’accesso al server telnet di MLDonkey.

Gli altri parametri credo si commentino da soli e non hanno bisogno di spiegazioni, ora supponiamo di voler scaricare tutti i link relativi ai video sul corso di Reti di Calcolatori:

http://dduniverse.net/ita/viewtopic.php?p=5691388

il comando da usare è il seguente:
[sourcecode language=”bash”]

$ sh download_link_mldonkey.sh http://dduniverse.net/ita/viewtopic.php?p=5691388 localhost

[/sourcecode]

 

Se tutto sarà andato per il meglio, la nostra bella bash ci restituirà qualcosa del genere a conferma del fatto che tutti i passaggi sono andati a buon fine

 

Buon Download a tutti, e ricordatevi che scaricare materiale coperto da copyright è illegale 😛