From acbf167f8cd9c95aba9d9f1ed79a37bbb9086d30 Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Tue, 4 Oct 2011 11:02:16 +0200 Subject: [PATCH] revert changes to new BNP website which has been removed --- weboob/backends/bnporc/backend.py | 4 +- weboob/backends/bnporc/browser.py | 27 ++++----- weboob/backends/bnporc/pages/__init__.py | 4 +- .../backends/bnporc/pages/account_coming.py | 16 ++--- .../backends/bnporc/pages/account_history.py | 60 +++++++++++-------- weboob/backends/bnporc/pages/accounts_list.py | 38 ++++++++---- weboob/backends/bnporc/pages/login.py | 27 ++------- weboob/backends/bnporc/pages/transfer.py | 12 ---- 8 files changed, 91 insertions(+), 97 deletions(-) diff --git a/weboob/backends/bnporc/backend.py b/weboob/backends/bnporc/backend.py index 0750f711f2..d13afe351c 100644 --- a/weboob/backends/bnporc/backend.py +++ b/weboob/backends/bnporc/backend.py @@ -76,12 +76,12 @@ def get_account(self, _id): def iter_history(self, account): with self.browser: - for history in self.browser.get_history(account.id): + for history in self.browser.get_history(account): yield history def iter_operations(self, account): with self.browser: - for coming in self.browser.get_coming_operations(account.id): + for coming in self.browser.get_coming_operations(account): yield coming def iter_transfer_recipients(self, ignored): diff --git a/weboob/backends/bnporc/browser.py b/weboob/backends/bnporc/browser.py index 9c8fadf6b6..29b628b4e0 100644 --- a/weboob/backends/bnporc/browser.py +++ b/weboob/backends/bnporc/browser.py @@ -34,18 +34,18 @@ class BNPorc(BaseBrowser): DOMAIN = 'www.secure.bnpparibas.net' PROTOCOL = 'https' ENCODING = None # refer to the HTML encoding - PAGES = {'.*pageId=unedescomptes.*': pages.AccountsList, - '.*pageId=releveoperations.*': pages.AccountHistory, + PAGES = {'.*identifiant=DOSSIER_Releves_D_Operation.*': pages.AccountsList, + '.*SAF_ROP.*': pages.AccountHistory, '.*Action=SAF_CHM.*': pages.ChangePasswordPage, - '.*pageId=mouvementsavenir.*': pages.AccountComing, + '.*NS_AVEDT.*': pages.AccountComing, '.*NS_AVEDP.*': pages.AccountPrelevement, '.*NS_VIRDF.*': pages.TransferPage, '.*NS_VIRDC.*': pages.TransferConfirmPage, '.*/NS_VIRDA\?stp=(?P\d+).*': pages.TransferCompletePage, + '.*Action=DSP_VGLOBALE.*': pages.LoginPage, '.*type=homeconnex.*': pages.LoginPage, '.*layout=HomeConnexion.*': pages.ConfirmPage, '.*SAF_CHM_VALID.*': pages.ConfirmPage, - '.*Action=DSP_MSG.*': pages.MessagePage, } def __init__(self, *args, **kwargs): @@ -81,8 +81,8 @@ def change_password(self, new_password): self.page.change_password(self.password, new_password) - if not self.is_on_page(pages.ConfirmPage) or self.page.get_error() is not None: - self.logger.error('Oops, unable to change password (%s)' % (self.page.get_error() if self.is_on_page(pages.ConfirmPage) else 'unknown')) + if not self.is_on_page(pages.ConfirmPage): + self.logger.error('Oops, unable to change password') return self.password, self.rotating_password = (new_password, self.password) @@ -123,18 +123,16 @@ def get_account(self, id): return None - def get_history(self, id): - self.location('/banque/portail/particulier/FicheA?contractId=%d&pageId=releveoperations&_eventId=changeOperationsPerPage&operationsPerPage=200' % int(id)) + def get_history(self, account): + if not self.is_on_page(pages.AccountHistory) or self.page.account.id != account.id: + self.location('/SAF_ROP?ch4=%s' % account.link_id) return self.page.get_operations() - def get_coming_operations(self, id): - if not self.is_on_page(pages.AccountsList): - self.location('/NSFR?Action=DSP_VGLOBALE') - execution = self.page.get_execution_id() - self.location('/banque/portail/particulier/FicheA?externalIAId=IAStatements&contractId=%d&pastOrPendingOperations=2&pageId=mouvementsavenir&execution=%s' % (int(id), execution)) + def get_coming_operations(self, account): + if not self.is_on_page(pages.AccountComing) or self.page.account.id != account.id: + self.location('/NS_AVEDT?ch4=%s' % account.link_id) return self.page.get_operations() - @check_expired_password def get_transfer_accounts(self): if not self.is_on_page(pages.TransferPage): self.location('/NS_VIRDF') @@ -142,7 +140,6 @@ def get_transfer_accounts(self): assert self.is_on_page(pages.TransferPage) return self.page.get_accounts() - @check_expired_password def transfer(self, from_id, to_id, amount, reason=None): if not self.is_on_page(pages.TransferPage): self.location('/NS_VIRDF') diff --git a/weboob/backends/bnporc/pages/__init__.py b/weboob/backends/bnporc/pages/__init__.py index 1e5cecafb0..97d3bd8b9f 100644 --- a/weboob/backends/bnporc/pages/__init__.py +++ b/weboob/backends/bnporc/pages/__init__.py @@ -22,10 +22,10 @@ from .account_coming import AccountComing from .account_history import AccountHistory from .transfer import TransferPage, TransferConfirmPage, TransferCompletePage -from .login import LoginPage, ConfirmPage, ChangePasswordPage, MessagePage +from .login import LoginPage, ConfirmPage, ChangePasswordPage class AccountPrelevement(AccountsList): pass __all__ = ['AccountsList', 'AccountComing', 'AccountHistory', 'LoginPage', - 'ConfirmPage', 'MessagePage', 'AccountPrelevement', 'ChangePasswordPage', + 'ConfirmPage', 'AccountPrelevement', 'ChangePasswordPage', 'TransferPage', 'TransferConfirmPage', 'TransferCompletePage'] diff --git a/weboob/backends/bnporc/pages/account_coming.py b/weboob/backends/bnporc/pages/account_coming.py index 17fcd6d820..39d22ca338 100644 --- a/weboob/backends/bnporc/pages/account_coming.py +++ b/weboob/backends/bnporc/pages/account_coming.py @@ -29,7 +29,7 @@ class AccountComing(BasePage): - LABEL_PATTERNS = [('^FACTURE CARTE DU (?P
\d{2})(?P\d{2})(?P\d{2}) (?P.*)', + LABEL_PATTERNS = [('^FACTURECARTEDU(?P
\d{2})(?P\d{2})(?P\d{2})(?P.*)', u'CB %(yy)s-%(mm)s-%(dd)s: %(text)s'), ('^PRELEVEMENT(?P.*)', 'Order: %(text)s'), ('^ECHEANCEPRET(?P.*)', u'Loan payment n°%(text)s'), @@ -38,18 +38,20 @@ class AccountComing(BasePage): def on_loaded(self): self.operations = [] - for tr in self.document.xpath('//table[@id="tableauOperations"]//tr'): - if 'typeop' in tr.attrib: + for tr in self.document.getiterator('tr'): + if tr.attrib.get('class', '') == 'hdoc1' or tr.attrib.get('class', '') == 'hdotc1': tds = tr.findall('td') if len(tds) != 3: continue - d = tr.attrib['dateop'] - d = date(int(d[4:8]), int(d[2:4]), int(d[0:2])) - label = tds[1].text or u'' + d = tds[0].getchildren()[0].attrib.get('name', '') + d = date(int(d[0:4]), int(d[4:6]), int(d[6:8])) + label = u'' + label += tds[1].text or u'' label = label.replace(u'\xa0', u'') for child in tds[1].getchildren(): if child.text: label += child.text if child.tail: label += child.tail + if tds[1].tail: label += tds[1].tail label = label.strip() for pattern, text in self.LABEL_PATTERNS: @@ -57,7 +59,7 @@ def on_loaded(self): if m: label = text % m.groupdict() - amount = tds[2].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r') + amount = tds[2].text.replace('.', '').replace(',', '.') operation = Operation(len(self.operations)) operation.date = d diff --git a/weboob/backends/bnporc/pages/account_history.py b/weboob/backends/bnporc/pages/account_history.py index affc9e436a..4774fb9795 100644 --- a/weboob/backends/bnporc/pages/account_history.py +++ b/weboob/backends/bnporc/pages/account_history.py @@ -35,34 +35,46 @@ class AccountHistory(BasePage): def on_loaded(self): self.operations = [] - for tr in self.document.xpath('//table[@id="tableCompte"]//tr'): - if len(tr.xpath('td[@class="debit"]')) == 0: - continue + for tr in self.document.getiterator('tr'): + if tr.attrib.get('class', '') == 'hdoc1' or tr.attrib.get('class', '') == 'hdotc1': + tds = tr.findall('td') + if len(tds) != 4: + continue + d = date(*reversed([int(x) for x in tds[0].text.split('/')])) + label = u'' + label += tds[1].text + label = label.replace(u'\xa0', u'') + for child in tds[1].getchildren(): + if child.text: label += child.text + if child.tail: label += child.tail + if tds[1].tail: label += tds[1].tail - id = tr.find('td').find('input').attrib['value'] - op = Operation(id) - op.label = tr.findall('td')[2].text.replace(u'\xa0', u'').strip() - op.date = date(*reversed([int(x) for x in tr.findall('td')[1].text.split('/')])) + label = label.strip() + category = NotAvailable + for pattern, _cat, _lab in self.LABEL_PATTERNS: + m = re.match(pattern, label) + if m: + category = _cat % m.groupdict() + label = _lab % m.groupdict() + break + else: + if ' ' in label: + category, useless, label = [part.strip() for part in label.partition(' ')] - op.category = NotAvailable - for pattern, _cat, _lab in self.LABEL_PATTERNS: - m = re.match(pattern, op.label) - if m: - op.category = _cat % m.groupdict() - op.label = _lab % m.groupdict() - break - else: - if ' ' in op.label: - op.category, useless, op.label = [part.strip() for part in op.label.partition(' ')] + amount = tds[2].text.replace('.', '').replace(',', '.') - debit = tr.xpath('.//td[@class="debit"]')[0].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r') - credit = tr.xpath('.//td[@class="credit"]')[0].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r') - if len(debit) > 0: - op.amount = - float(debit) - else: - op.amount = float(credit) + # if we don't have exactly one '.', this is not a floatm try the next + operation = Operation(len(self.operations)) + if amount.count('.') != 1: + amount = tds[3].text.replace('.', '').replace(',', '.') + operation.amount = float(amount) + else: + operation.amount = - float(amount) - self.operations.append(op) + operation.date = d + operation.label = label + operation.category = category + self.operations.append(operation) def get_operations(self): return self.operations diff --git a/weboob/backends/bnporc/pages/accounts_list.py b/weboob/backends/bnporc/pages/accounts_list.py index 0c9b5c4757..748a7cc5ba 100644 --- a/weboob/backends/bnporc/pages/accounts_list.py +++ b/weboob/backends/bnporc/pages/accounts_list.py @@ -39,17 +39,34 @@ def on_loaded(self): def get_list(self): l = [] for tr in self.document.getiterator('tr'): - if not 'class' in tr.attrib and tr.find('td') is not None and tr.find('td').attrib.get('class', '') == 'typeTitulaire': + if tr.attrib.get('class', '') == 'comptes': account = Account() - account.id = tr.xpath('.//td[@class="libelleCompte"]/input')[0].attrib['id'][len('libelleCompte'):] - account.label = tr.xpath('.//td[@class="libelleCompte"]/a')[0].text.strip() + for td in tr.getiterator('td'): + if td.attrib.get('headers', '').startswith('Numero_'): + id = td.text + account.id = ''.join(id.split(' ')).strip() + elif td.attrib.get('headers', '').startswith('Libelle_'): + a = td.findall('a') + label = unicode(a[0].text) + account.label = label.strip() + m = self.LINKID_REGEXP.match(a[0].attrib.get('href', '')) + if m: + account.link_id = m.group(1) + elif td.attrib.get('headers', '').startswith('Solde'): + a = td.findall('a') + balance = a[0].text + balance = balance.replace('.','').replace(',','.') + account.balance = float(balance) + elif td.attrib.get('headers', '').startswith('Avenir'): + a = td.findall('a') + # Some accounts don't have a "coming" + if len(a): + coming = a[0].text + coming = coming.replace('.','').replace(',','.') + account.coming = float(coming) + else: + account.coming = NotAvailable - tds = tr.findall('td') - account.balance = float(tds[3].find('a').text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')) - if tds[4].find('a') is not None: - account.coming = float(tds[4].find('a').text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')) - else: - account.coming = NotAvailable l.append(account) if len(l) == 0: @@ -59,6 +76,3 @@ def get_list(self): if div.text.strip() == 'Vous avez atteint la date de fin de vie de votre code secret.': raise PasswordExpired(div.text.strip()) return l - - def get_execution_id(self): - return self.document.xpath('//input[@name="execution"]')[0].attrib['value'] diff --git a/weboob/backends/bnporc/pages/login.py b/weboob/backends/bnporc/pages/login.py index 078dce224a..66332b56e0 100644 --- a/weboob/backends/bnporc/pages/login.py +++ b/weboob/backends/bnporc/pages/login.py @@ -18,7 +18,6 @@ # along with weboob. If not, see . -import re from weboob.tools.mech import ClientForm import urllib from logging import error @@ -60,21 +59,8 @@ def login(self, login, password): class ConfirmPage(BasePage): - def get_error(self): - for td in self.document.xpath('//td[@class="hdvon1"]'): - if td.text: - return td.text.strip() - return None - - def get_relocate_url(self): - script = self.document.xpath('//script')[0] - m = re.match('document.location.replace\("(.*)"\)', script.text[script.text.find('document.location.replace'):]) - if m: - return m.group(1) - -class MessagePage(BasePage): - def on_loaded(self): - pass + pass + class ChangePasswordPage(BasePage): def change_password(self, current, new): @@ -92,12 +78,7 @@ def change_password(self, current, new): data = {'ch1': code_current, 'ch2': code_new, - 'ch3': code_new, - 'radiobutton3': 'radiobutton', - 'x': 12, - 'y': 9, + 'ch3': code_new } - headers = {'Referer': self.url} - request = self.browser.request_class('https://www.secure.bnpparibas.net/SAF_CHM_VALID', urllib.urlencode(data), headers) - self.browser.location(request) + self.browser.location('/SAF_CHM_VALID', urllib.urlencode(data)) diff --git a/weboob/backends/bnporc/pages/transfer.py b/weboob/backends/bnporc/pages/transfer.py index df551eda48..2c443aa5c3 100644 --- a/weboob/backends/bnporc/pages/transfer.py +++ b/weboob/backends/bnporc/pages/transfer.py @@ -23,7 +23,6 @@ from weboob.tools.browser import BasePage from weboob.tools.ordereddict import OrderedDict from weboob.capabilities.bank import TransferError -from ..errors import PasswordExpired __all__ = ['TransferPage', 'TransferConfirmPage', 'TransferCompletePage'] @@ -37,11 +36,6 @@ def __init__(self, id, label, send_checkbox, receive_checkbox): self.receive_checkbox = receive_checkbox class TransferPage(BasePage): - def on_loaded(self): - for td in self.document.xpath('//td[@class="hdvon1"]'): - if td.text and 'Vous avez atteint le seuil de' in td.text: - raise PasswordExpired(td.text.strip()) - def get_accounts(self): accounts = OrderedDict() for table in self.document.getiterator('table'): @@ -61,12 +55,6 @@ def get_accounts(self): def transfer(self, from_id, to_id, amount, reason): accounts = self.get_accounts() - # Transform RIBs to short IDs - if len(str(from_id)) == 23: - from_id = str(from_id)[5:21] - if len(str(to_id)) == 23: - to_id = str(to_id)[5:21] - try: sender = accounts[from_id] except KeyError: -- GitLab