Résoudre les problèmes d’encoding avec Python Mechanize

Un de ces jours il faudra qu’on fasse un petit post sur la gestion de l’encoding en Python. En attendant, voici une astuce pour eviter une des erreurs les plus énervantes pour une débutant:

UnicodeDecodeError: 'utf8' codec can't decode byte machin in position truc

De quoi choper un smic d’amende pour infraction au code de moralité du langage.

Contrairement à BeautifulSoup, mechanize n’essaye pas de détecter l’encoding de la page, et il vous retourne directement la soupe de bytes qu’il reçoit en réponse. Ca marche jusqu’à ce que vous tombiez sur un site avec un encodage différent de celui de votre système.

Heureusement maintenant, la plupart des sites ont la politesse de déclarer leur encoding dans une balise meta, que l’on peut récupérer dans les headers. Du coup on peut convertir facilement le HTML de la page en unicode:

import re
import mechanize
response = mechanize.Browser().open('http://google.com')
# on chope l'encoding dans les headers
# si ça marche pas on beugle une exception
content_type = response.info().getheader('content-type') 
try:
    encoding = re.search(r'charset=([^\s]+)', content_type).groups()[0]
except AttributeError, IndexError:
    raise ValueError('Unable to guess the page encoding')
# et on decode tout ça
return response.read().decode(encoding)

Par facilité, nous on utilise carrément une sous-classe, vu que 99% du temps on a besoin que du HTML et qu’on se sert essentiellement de mechanize comme un gros urllib2 avec plein de paramètres:

import re
import mechanize
class Browser(mechanize.Browser):
 
    def get_content_as_unicode(self, url):
        response = self.open(url)
        content_type = response.info().getheader('content-type')
        try:
            encoding = re.search(r'charset=([^\s]+)', content_type).groups()[0]
        except AttributeError, IndexError:
            raise ValueError('Unable to guess the page encoding')
        return response.read().decode(encoding)

Hop :

>>> type(Browser().get_content_as_unicode('http://google.com'))
<type 'unicode'>

Plus besoin de coquillages maintenant !

Articles similaires:

  1. Quand Mechanize bouffe toute votre RAM et que vous ne savez pas pourquoi….
  2. Filtrer les propos pornos avec Python
  3. Valider une adresse email avec une regex en Python

flattr this!

2 comments

  1. fallait le savoir !

  2. merci !

Flux RSS des commentaires

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Jouer à mario en attendant que les autres répondent