fix carrefourbanque to use new website (and rewrite it with browser2)

This commit is contained in:
Romain Bignon 2014-04-26 12:01:09 +02:00
commit 73cb61fec7
3 changed files with 59 additions and 154 deletions

View file

@ -18,6 +18,7 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.capabilities.base import find_object
from weboob.capabilities.bank import ICapBank, AccountNotFound from weboob.capabilities.bank import ICapBank, AccountNotFound
from weboob.tools.backend import BaseBackend, BackendConfig from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValueBackendPassword from weboob.tools.value import ValueBackendPassword
@ -35,8 +36,8 @@ class CarrefourBanqueBackend(BaseBackend, ICapBank):
VERSION = '0.i' VERSION = '0.i'
DESCRIPTION = u'Carrefour Banque' DESCRIPTION = u'Carrefour Banque'
LICENSE = 'AGPLv3+' LICENSE = 'AGPLv3+'
CONFIG = BackendConfig(ValueBackendPassword('login', label=u'Référent client', masked=False), CONFIG = BackendConfig(ValueBackendPassword('login', label=u'Votre Identifiant Internet', masked=False),
ValueBackendPassword('password', label=u"Code d'accès", regexp='\d+')) ValueBackendPassword('password', label=u"Code d'accès", regexp=u'\d+'))
BROWSER = CarrefourBanque BROWSER = CarrefourBanque
def create_default_browser(self): def create_default_browser(self):
@ -44,26 +45,10 @@ class CarrefourBanqueBackend(BaseBackend, ICapBank):
self.config['password'].get()) self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
with self.browser: return self.browser.get_accounts_list()
return self.browser.get_accounts_list()
def get_account(self, _id): def get_account(self, _id):
with self.browser: return find_object(self.browser.get_accounts_list(), id=_id, error=AccountNotFound)
account = self.browser.get_account(_id)
if account:
return account
else:
raise AccountNotFound()
def iter_history(self, account): def iter_history(self, account):
with self.browser: return self.browser.iter_history(account)
for tr in self.browser.iter_history(account):
if not tr._coming:
yield tr
def iter_coming(self, account):
with self.browser:
for tr in self.browser.iter_history(account):
if tr._coming:
yield tr

View file

@ -18,36 +18,23 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
import urllib from weboob.tools.browser2 import LoginBrowser, URL, need_login
from weboob.tools.browser import BrowserIncorrectPassword
from weboob.tools.browser import BaseBrowser from .pages import LoginPage, HomePage, TransactionsPage
from .pages import LoginPage, HomePage, AccountsPage, TransactionsPage
__all__ = ['CarrefourBanque'] __all__ = ['CarrefourBanque']
class CarrefourBanque(BaseBrowser): class CarrefourBanque(LoginBrowser):
PROTOCOL = 'https' BASEURL = 'https://www.carrefour-banque.fr'
DOMAIN = 'services.carrefour-banque.fr'
ENCODING = 'iso-8859-15'
PAGES = {'https?://services.carrefour-banque.fr/s2pnet/publ/identification.do': LoginPage,
'https?://services.carrefour-banque.fr/stscripts/run.stn/s2p/SommairePS2P': HomePage,
'https?://services.carrefour-banque.fr/s2pnet/priv/disponible.do': AccountsPage,
'https?://services.carrefour-banque.fr/s2pnet/priv/consult.do\?btnTelechargement': (TransactionsPage, 'raw'),
}
def is_logged(self): login = URL('/espace-client/connexion', LoginPage)
return self.page is not None and not self.is_on_page(LoginPage) home = URL('/espace-client$', HomePage)
transactions = URL('/espace-client/carte-credit/solde-dernieres-operations.*', TransactionsPage)
def home(self): def do_login(self):
if self.is_logged():
self.location('/s2pnet/priv/disponible.do')
else:
self.login()
def login(self):
""" """
Attempt to log in. Attempt to log in.
Note: this method does nothing if we are already logged in. Note: this method does nothing if we are already logged in.
@ -55,41 +42,21 @@ class CarrefourBanque(BaseBrowser):
assert isinstance(self.username, basestring) assert isinstance(self.username, basestring)
assert isinstance(self.password, basestring) assert isinstance(self.password, basestring)
if self.is_logged(): self.login.go()
return self.page.enter_login(self.username)
self.page.enter_password(self.password)
args = {'login': '', if not self.home.is_here():
'loginCBPASS': self.username.encode(self.ENCODING), raise BrowserIncorrectPassword()
'motPasse': self.password.encode(self.ENCODING),
'testJS': 'true',
'x': 8,
'y': 4,
}
self.location('https://services.carrefour-banque.fr/s2pnet/publ/identification.do', urllib.urlencode(args), no_login=True)
assert self.is_on_page(LoginPage)
# raises BrowserIncorrectPassword if no redirect form is found
self.page.redirect()
@need_login
def get_accounts_list(self): def get_accounts_list(self):
if not self.is_on_page(AccountsPage): self.home.stay_or_go()
self.location('/s2pnet/priv/disponible.do')
return self.page.get_list() return self.page.get_list()
def get_account(self, id): @need_login
assert isinstance(id, basestring)
l = self.get_accounts_list()
for a in l:
if a.id == id:
return a
return None
def iter_history(self, account): def iter_history(self, account):
self.location('/s2pnet/priv/consult.do?btnTelechargement') self.location(account._link)
assert self.is_on_page(TransactionsPage) assert self.transactions.is_here()
return self.page.get_history(account) return self.page.get_history(account)

View file

@ -18,102 +18,55 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
import datetime
from decimal import Decimal
import re import re
from mechanize import FormNotFoundError
from weboob.tools.browser import BasePage, BrowserIncorrectPassword from weboob.tools.browser2.page import HTMLPage, ListElement, ItemElement, method, LoggedPage
from weboob.tools.browser2.filters import Regexp, CleanText, CleanDecimal, Format, Link
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.capabilities.bank.transactions import FrenchTransaction
__all__ = ['LoginPage', 'AccountsPage', 'TransactionsPage'] __all__ = ['LoginPage', 'HomePage', 'TransactionsPage']
class LoginPage(BasePage): class LoginPage(HTMLPage):
def redirect(self): def enter_login(self, username):
try: form = self.get_form(nr=0)
self.browser.select_form(name='redirectEpargne') form['name'] = username
self.browser.submit(nologin=True) form.submit()
except FormNotFoundError:
raise BrowserIncorrectPassword() def enter_password(self, password):
form = self.get_form(nr=0)
form['pass'] = password
form.submit()
class HomePage(BasePage): class HomePage(LoggedPage, HTMLPage):
pass @method
class get_list(ListElement):
item_xpath = '//div[@class="three_contenu_table"]'
class item(ItemElement):
klass = Account
obj_id = Regexp(CleanText('./div[@class="carte_col_leftcol"]/p'), r'(\d+)')
obj_label = CleanText('./div[@class="carte_col_leftcol"]/h2')
obj_balance = CleanDecimal(Format('-%s', CleanText('.//div[@class="catre_col_one"]/h2')))
obj_currency = FrenchTransaction.Currency('.//div[@class="catre_col_one"]/h2')
obj__link = Link('.//a[contains(@href, "solde-dernieres-operations")]')
class AccountsPage(BasePage): class Transaction(FrenchTransaction):
def get_list(self): PATTERNS = [(re.compile(r'^(?P<text>.*?) (?P<dd>\d{2})/(?P<mm>\d{2})$'), FrenchTransaction.TYPE_CARD)]
div = self.document.xpath('//div[@id="descriptifdroite"]')[0]
account = Account()
account.id = re.search(u'(\d+)', div.xpath('.//div[@class="credithauttexte"]')[0].text).group(1)
account.label = u'Carte PASS'
account.balance = Decimal('0')
for tr in div.xpath('.//table/tr'):
tds = tr.findall('td')
if len(tds) < 3:
continue
label = u''.join([txt.strip() for txt in tds[1].itertext()])
value = u''.join([txt.strip() for txt in tds[2].itertext()])
if 'encours depuis le dernier' in label.lower():
coming = u'-' + value
account.coming = Decimal(FrenchTransaction.clean_amount(coming))
account.currency = account.get_currency(coming)
elif u'arrêté de compte' in label.lower():
m = re.search(u'(\d+)/(\d+)/(\d+)', label)
if m:
account._outstanding_date = datetime.date(*reversed(map(int, m.groups())))
break
yield account
class TransactionsPage(BasePage): class TransactionsPage(LoggedPage, HTMLPage):
COL_DATE = 0 @method
COL_TEXT = 1 class get_history(Transaction.TransactionsElement):
COL_AMOUNT = 2 head_xpath = '//table[@id="creditHistory"]//thead/tr/th'
item_xpath = '//table[@id="creditHistory"]/tbody/tr'
def get_history(self, account): class item(Transaction.TransactionElement):
transactions = [] obj_id = None
last_order = None obj_type = Transaction.TYPE_CARD
for tr in self.document.split('\n')[1:]:
cols = tr.split(';')
if len(cols) < 4:
continue
t = FrenchTransaction(0)
date = cols[self.COL_DATE]
raw = cols[self.COL_TEXT]
amount = cols[self.COL_AMOUNT]
t.parse(date, re.sub(r'[ ]+', ' ', raw))
if t.raw.startswith('PRELEVEMENT ACHATS DIFFERES'):
t._coming = False
if last_order is None:
last_order = t.date
else:
t._coming = True
t.set_amount(amount)
transactions.append(t)
# go to the previous stop date before the last order
while last_order is not None and last_order.day != account._outstanding_date.day:
last_order = last_order - datetime.timedelta(days=1)
for t in transactions:
if t.date <= last_order:
t._coming = False
return iter(transactions)