Sam & Max » mechanize http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Simuler un cookie avec Mechanize en python http://sametmax.com/simuler-un-cookie-avec-mechanize-en-python/ http://sametmax.com/simuler-un-cookie-avec-mechanize-en-python/#comments Sun, 20 May 2012 19:46:51 +0000 http://sametmax.com/?p=667 Il peut arriver que l’on ai besoin de simuler la présence d’un cookie lors de l’exploration d’un site avec Mechanize .
Un exemple tout bête l’autre jour j’essayais de me connecter à un site qui demandait une vérif d’âge, impossible de simuler le click sur “ENTER” car le bouton était géré par Jquery (et Mechanize ne fait pas de js).
Après quelques debug je me suis aperçu que le site stockait dans un cookie la confirmation d’âge sous la forme “age_verified”, valeur 1.

il suffisait donc d’avoir ce cookie et le site nous laissait tranquille.
Avec Mechanize il est possible d’ajouter un cookie dans son cookie jar, voici comment:

import mechanize
 
# Browser use mechanize
br = mechanize.Browser()
 
# Cookie Jar
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
 
# add a cookie to cookie jar
cj.set_cookie(cookielib.Cookie(0, 'age_verified', '1', '80', False, 'www.nom_de_domaine.com', True, False, '/', True, False, None, False, None, None, None))
 
# Browser options
br.set_handle_redirect(True)

Où:
age_verified : SID du cookie
1: valeur
80: port
www.nom_de_domaine.com : le nom de domaine du site auquel le cookie appartient
/: path du cookie

Un peu plus sur les options:

cookielib.Cookie(version=0, name='SID', value=self._sid, port=None, port_specified=False, domain='.google.com', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=False, expires='1600000000', discard=False, comment=None, comment_url=None, rest={})

Quelques liens:
http://nullege.com/codes/search/cookielib.Cookie
http://docs.python.org/library/cookielib.html
http://wwwsearch.sourceforge.net/mechanize/hints.html

]]> http://sametmax.com/simuler-un-cookie-avec-mechanize-en-python/feed/ 0 Résoudre les problèmes d’encoding avec Python Mechanize 2 http://sametmax.com/resoudre-les-problemes-dencoding-avec-python-mechanize/ http://sametmax.com/resoudre-les-problemes-dencoding-avec-python-mechanize/#comments Wed, 28 Mar 2012 17:02:46 +0000 http://sametmax.com/?p=306 UnicodeDecodeError: 'utf8' codec can't decode byte machin in position truc vous fait faire des cauchemars ? Suivez le guide.]]> 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 éviter une des erreurs les plus énervantes pour un 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’essaie pas de détecter l’encoding de la page, et vous retourne directement la soupe de bytes qu’il reçoit en réponse. Ça 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 !

]]>
http://sametmax.com/resoudre-les-problemes-dencoding-avec-python-mechanize/feed/ 2
Quand Mechanize bouffe toute votre RAM et que vous ne savez pas pourquoi…. 1 http://sametmax.com/quand-mechanize-bouffe-toute-votre-ram-et-que-vous-ne-savez-pas-pourquoi/ http://sametmax.com/quand-mechanize-bouffe-toute-votre-ram-et-que-vous-ne-savez-pas-pourquoi/#comments Wed, 21 Mar 2012 17:36:52 +0000 http://sametmax.com/?p=282 En revenant de Bangla Road l’autre soir, je me connecte sur l’admin d’un de nos serveurs et je m’aperçois qu’un script de grabbing bouffait à lui tout seul plus de 30% de la mémoire. Après quelques recherches, Sam me fait part d’un article sur Mechanize et sa tendance à avoir un history plutôt vorace en RAM.

Le coupable était Mechanize avec le chandelier dans le salon :

En effet, Mechanize par défaut sauve tout l’historique de votre navigation, donc imaginez le carnage quand vous avez un script qui est censé scanner des milliers de pages internet…

Pour lui couper le sifflet on peut utiliser cette méthode :

 
import mechanize
from mechanize import History
 
class MaxHistory(History):
    """
        History implementation with a size limit.
    """
    def __init__(self, max_history=None):
        self._history = []  # LIFO
        self.max_history = max_history
 
    def add(self, request, response):
        self._history.append((request, response))
 
        if (self.max_history is not None and self._history
            and self.max_history <= len(self._history)):
            self._history.pop(0)
 
br = mechanize.Browser(history=MaxHistory(max_history=10))
Browser.open("http://sametmax.com/")

Et voilà !
Plus de problème de mémoire. Merci bibi.

]]>
http://sametmax.com/quand-mechanize-bouffe-toute-votre-ram-et-que-vous-ne-savez-pas-pourquoi/feed/ 1