Blog of :/blog/weboob/Browser2_:_Nouvelle_gestion_des_pages_avec_la_classe_URL.html

Browser2 : Nouvelle gestion des pages avec la classe URL

Cet article fait partie d'une série sur le Browser2.

Le browser est séparé en deux niveaux : les pages, qui sont représentées chacune par des classes dérivées de BasePage contenant le code nécessaire au parsing du contenu des pages, et le Browser lui-même qui sert de contrôleur pour la navigation.

L'ancien système

Voici ce à quoi ressemble le système de pages de la première version du browser :

class CreditMutuelBrowser(BaseBrowser):
    PROTOCOL = 'https'
    DOMAIN = 'www.creditmutuel.fr'
    PAGES = {'https://www.creditmutuel.fr/.*/fr/banque/situation_financiere.cgi': AccountsPage,
             'https://www.creditmutuel.fr/.*/fr/banque/mouvements.cgi.*': OperationsPage,
             'https://www.creditmutuel.fr/.*/fr/banque/nr/nr_devbooster.aspx.*': OperationsPage,
            }

    def get_accounts_list(self):
        if not self.is_on_page(AccountsPage):
            self.location('https://www.creditmutuel.fr/%s/fr/banque/situation_financiere.cgi' % self.currentSubBank)
        return self.page.get_list()

Un dictionnaire fait la correspondance entre une expression régulière d'url et la classe d'une page (dérivée de BasePage), et lorsque l'on fait un appel à la méthode location() il tente de retrouver la page à instancier en fonction de l'url. On peut donc ainsi savoir sur quelle page on se trouve avec la méthode is_on_page(klass), qui est un alias à isinstance(self.page, klass).

La classe URL

Voici maintenant comment on décrit les pages dans le browser2 :

class CreditMutuelBrowser(PagesBrowser):
    BASEURL = 'https://www.creditmutuel.fr'

    accounts =   URL('/(?P<subbank>.*)/fr/banque/situation_financiere.cgi',
                     AccountsPage)
    operations = URL('/(?P<subbank>.*)/fr/banque/mouvements.cgi.*',
                     '/(?P<subbank>.*)/fr/banque/nr/nr_devbooster.aspx.*',
                     OperationsPage)

Plutôt que d'avoir un dictionnaire, on décrit des attributs à la classe avec associé d'une part une liste de chemins, et d'autre part la classe à instancier. L'attribut BASEURL permet de préciser le chemin plutôt que des urls complètes.

En outre, la résolution se fait maintenant dans l'ordre de déclaration, ce qui est très utile dans le cas de conflits.

Reverse

Vous avez sans doutes constaté le fait que dans nos expressions régulières ont été précisés des noms pour le pattern subbank. Ceci permet d'une part de récupérer les valeurs dans l'instance de BasePage, mais surtout d'utiliser URL comme un moyen d'accéder directement aux pages avec des paramètres variables.

En effet, URL fournit deux méthodes très sympathiques, URL.go() et URL.stay_or_go(), ce qui nous permet de réécrire la méthode get_accounts_list comme ceci :

    def get_accounts_list(self):
        return self.accounts.stay_or_go(subbank=self.currentSubBank).get_accounts()

L'avantage majeur de ce système est donc d'éviter, comme dans l'exemple du browser1, d'avoir une redondance entre les URLs à associer aux BasePage et les appels à location() où l'on doit à nouveau spécifier l'url.

Liens vers la documentation