def _add_account(self, accounts, link, label, account_type, balance): info = self._get_account_info(link, accounts) if info is None: self.logger.warning('Unable to parse account %r: %r' % (label, link)) return account = Account() account.id = info['id'] if is_rib_valid(info['id']): account.iban = rib2iban(info['id']) account._info = info account.label = label account.type = self.ACCOUNT_TYPES.get(label, info['acc_type'] if 'acc_type' in info else account_type) balance = balance or self.get_balance(account) account.balance = Decimal(FrenchTransaction.clean_amount(balance)) if balance and balance is not NotAvailable else NotAvailable account.currency = account.get_currency(balance) if balance and balance is not NotAvailable else NotAvailable account._card_links = [] if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts: a = accounts[account.id] if not a.coming: a.coming = Decimal('0.0') if account.balance and account.balance is not NotAvailable: a.coming += account.balance a._card_links.append(account._info) return accounts[account.id] = account
def _add_account(self, accounts, link, label, account_type, balance): info = self._get_account_info(link) if info is None: self.logger.warning('Unable to parse account %r: %r' % (label, link)) return account = Account() account.id = info['id'] account.iban = u'FR76' + info['id'] account._info = info account.label = label account.type = info['acc_type'] if 'acc_type' in info else account_type account.balance = Decimal(FrenchTransaction.clean_amount( balance)) if balance else self.get_balance(account) account.currency = account.get_currency(balance) account._card_links = [] if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts: a = accounts[account.id] if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance a._card_links.append(account._info) return accounts[account.id] = account
def get_accounts_list(self): for table in self.document.xpath('//div[@class="comptestabl"]/table'): try: account_type = self.ACCOUNT_TYPES[table.get('summary')] if not account_type: account_type = self.ACCOUNT_TYPES[table.xpath( './caption/text()')[0].strip()] except (IndexError, KeyError): account_type = Account.TYPE_UNKNOWN for tr in table.xpath('./tbody/tr'): cols = tr.findall('td') link = cols[0].find('a') if link is None: continue a = Account() a.type = account_type a.id = unicode( re.search('([A-Z\d]{4}[A-Z\d\*]{3}[A-Z\d]{4})', link.attrib['title']).group(1)) a.label = unicode(link.attrib['title'].replace( '%s ' % a.id, '')) tmp_balance = self.parser.tocleanstring(cols[1]) a.currency = a.get_currency(tmp_balance) a.balance = Decimal(Transaction.clean_amount(tmp_balance)) a._card_links = [] a._link_id = link.attrib['href'] yield a
def get_loan_list(self): accounts = OrderedDict() # New website for table in self.document.xpath('//div[@class="panel"]'): title = table.getprevious() if title is None: continue account_type = self.ACCOUNT_TYPES.get(self.parser.tocleanstring(title), Account.TYPE_UNKNOWN) for tr in table.xpath('./table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]'): tds = tr.findall('td') if len(tds) == 0 : continue for i in tds[0].xpath('.//a/strong'): label = i.text.strip() break balance = Decimal(FrenchTransaction.clean_amount(self.parser.tocleanstring(tds[-1]))) account = Account() account.id = label.split(' ')[-1] account.label = unicode(label) account.type = account_type account.balance = -abs(balance) account.currency = account.get_currency(self.parser.tocleanstring(tds[-1])) account._card_links = [] accounts[account.id] = account return accounts.itervalues()
def get_loan_list(self): accounts = OrderedDict() # Old website for tr in self.doc.xpath( '//table[@cellpadding="1"]/tr[not(@class) and td[a]]'): tds = tr.findall('td') account = Account() account.id = CleanText('./a')(tds[2]).split('-')[0].strip() account.label = CleanText('./a')(tds[2]).split('-')[-1].strip() account.type = Account.TYPE_LOAN account.balance = -CleanDecimal('./a', replace_dots=True)(tds[4]) account.currency = account.get_currency(CleanText('./a')(tds[4])) accounts[account.id] = account if len(accounts) == 0: # New website for table in self.doc.xpath('//div[@class="panel"]'): title = table.getprevious() if title is None: continue account_type = self.ACCOUNT_TYPES.get( CleanText('.')(title), Account.TYPE_UNKNOWN) for tr in table.xpath( './table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]' ): tds = tr.findall('td') if len(tds) == 0: continue for i in tds[0].xpath('.//a/strong'): label = i.text.strip() break if len(tds) == 3 and Decimal( FrenchTransaction.clean_amount( CleanText('.')(tds[-2]))) and any( cls in Attr('.', 'id')(tr) for cls in ['dgImmo', 'dgConso']) == False: # in case of Consumer credit or revolving credit, we substract avalaible amount with max amout # to get what was spend balance = Decimal( FrenchTransaction.clean_amount( CleanText('.')(tds[-2]))) - Decimal( FrenchTransaction.clean_amount( CleanText('.')(tds[-1]))) else: balance = Decimal( FrenchTransaction.clean_amount( CleanText('.')(tds[-1]))) account = Account() account.id = label.split(' ')[-1] account.label = unicode(label) account.type = account_type account.balance = -abs(balance) account.currency = account.get_currency( CleanText('.')(tds[-1])) account._card_links = [] accounts[account.id] = account return accounts.itervalues()
def parse_table(self, what): tables = self.document.xpath("//table[@id='%s']" % what, smart_strings=False) if len(tables) < 1: return lines = tables[0].xpath(".//tbody/tr") for line in lines: account = Account() tmp = line.xpath("./td//a")[0] account.label = to_unicode(tmp.text) account._link_id = tmp.get("href") if "BourseEnLigne" in account._link_id: continue tmp = line.xpath("./td/span/strong") if len(tmp) >= 2: tmp_id = tmp[0].text tmp_balance = tmp[1].text else: tmp_id = line.xpath("./td//span")[1].text tmp_balance = tmp[0].text account.id = tmp_id account.currency = account.get_currency(tmp_balance) account.balance = Decimal(FrenchTransaction.clean_amount(tmp_balance)) if account.id in self.accounts: a = self.accounts[account.id] a._card_links.append(account._link_id) if not a.coming: a.coming = Decimal("0.0") a.coming += account.balance else: account._card_links = [] self.accounts[account.id] = account
def _add_account(self, accounts, link, label, account_type, balance): info = self._get_account_info(link) if info is None: self.logger.warning('Unable to parse account %r: %r' % (label, link)) return account = Account() account.id = info['id'] account.iban = u'FR76' + info['id'] account._info = info account.label = label account.type = info['acc_type'] if 'acc_type' in info else account_type account.balance = Decimal(FrenchTransaction.clean_amount(balance)) if balance else self.get_balance(account) account.currency = account.get_currency(balance) account._card_links = [] if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts: a = accounts[account.id] if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance a._card_links.append(account._info) return accounts[account.id] = account
def get_loan_list(self): accounts = OrderedDict() # New website for table in self.document.xpath('//div[@class="panel"]'): title = table.getprevious() if title is None: continue account_type = self.ACCOUNT_TYPES.get( self.parser.tocleanstring(title), Account.TYPE_UNKNOWN) for tr in table.xpath( './table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]' ): tds = tr.findall('td') if len(tds) == 0: continue for i in tds[0].xpath('.//a/strong'): label = i.text.strip() break balance = Decimal( FrenchTransaction.clean_amount( self.parser.tocleanstring(tds[-1]))) account = Account() account.id = label.split(' ')[-1] account.label = unicode(label) account.type = account_type account.balance = -abs(balance) account.currency = account.get_currency( self.parser.tocleanstring(tds[-1])) account._card_links = [] accounts[account.id] = account return accounts.itervalues()
def get_list(self): accounts = OrderedDict() for tr in self.document.getiterator('tr'): first_td = tr.getchildren()[0] if (first_td.attrib.get('class', '') == 'i g' or first_td.attrib.get('class', '') == 'p g') \ and first_td.find('a') is not None: a = first_td.find('a') link = a.get('href', '') if link.startswith('POR_SyntheseLst'): continue url = urlparse(link) p = parse_qs(url.query) if not 'rib' in p: continue for i in (2,1): balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text) currency = Account.get_currency(tr.getchildren()[i].text) if len(balance) > 0: break balance = Decimal(balance) id = p['rib'][0] if id in accounts: account = accounts[id] if not account.coming: account.coming = Decimal('0.0') account.coming += balance account._card_links.append(link) continue account = Account() account.id = id account.label = unicode(a.text).strip().lstrip(' 0123456789').title() account._link_id = link account._card_links = [] # Find accounting amount page = self.browser.get_document(self.browser.openurl(link)) coming = self.find_amount(page, u"Opérations à venir") accounting = self.find_amount(page, u"Solde comptable") if accounting is not None and accounting + (coming or Decimal('0')) != balance: self.logger.warning('%s + %s != %s' % (accounting, coming, balance)) if accounting is not None: balance = accounting if coming is not None: account.coming = coming account.balance = balance account.currency = currency accounts[account.id] = account return accounts.itervalues()
def get_loan_list(self): accounts = OrderedDict() # Old website for tr in self.doc.xpath('//table[@cellpadding="1"]/tr[not(@class) and td[a]]'): tds = tr.findall('td') account = Account() account.id = CleanText('./a')(tds[2]).split('-')[0].strip() account.label = CleanText('./a')(tds[2]).split('-')[-1].strip() account.type = Account.TYPE_LOAN account.balance = -CleanDecimal('./a', replace_dots=True)(tds[4]) account.currency = account.get_currency(CleanText('./a')(tds[4])) accounts[account.id] = account if len(accounts) == 0: # New website for table in self.doc.xpath('//div[@class="panel"]'): title = table.getprevious() if title is None: continue account_type = self.ACCOUNT_TYPES.get(CleanText('.')(title), Account.TYPE_UNKNOWN) for tr in table.xpath('./table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]'): tds = tr.findall('td') if len(tds) == 0 : continue for i in tds[0].xpath('.//a/strong'): label = i.text.strip() break if len(tds) == 3 and Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-2]))) and any(cls in Attr('.', 'id')(tr) for cls in ['dgImmo', 'dgConso']) == False: # in case of Consumer credit or revolving credit, we substract avalaible amount with max amout # to get what was spend balance = Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-2]))) - Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-1]))) else: balance = Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-1]))) account = Loan() account.id = label.split(' ')[-1] account.label = unicode(label) account.type = account_type account.balance = -abs(balance) account.currency = account.get_currency(CleanText('.')(tds[-1])) account._card_links = [] if "immobiliers" in CleanText('.')(title): xp = './/div[contains(@id, "IdDivDetail")]/table/tbody/tr[contains(@id, "%s")]/td' account.maturity_date = Date(CleanText(xp % 'IdDerniereEcheance'), dayfirst=True, default=NotAvailable)(tr) account.total_amount = CleanDecimal(CleanText(xp % 'IdCapitalEmprunte'), replace_dots=True, default=NotAvailable)(tr) account.subscription_date = Date(CleanText(xp % 'IdDateOuverture'), dayfirst=True, default=NotAvailable)(tr) account.next_payment_date = Date(CleanText(xp % 'IdDateProchaineEcheance'), dayfirst=True, default=NotAvailable)(tr) account.rate = CleanDecimal(CleanText(xp % 'IdTaux'), replace_dots=True, default=NotAvailable)(tr) account.next_payment_amount = CleanDecimal(CleanText(xp % 'IdMontantEcheance'), replace_dots=True, default=NotAvailable)(tr) elif "renouvelables" in CleanText('.')(title): self.go_loans_conso(tr) d = self.browser.loans_conso() if d: account.total_amount = d['contrat']['creditMaxAutorise'] account.available_amount = d['situationCredit']['disponible'] account.next_payment_amount = d['situationCredit']['mensualiteEnCours'] accounts[account.id] = account return accounts.values()
def get_list(self): accounts = [] for tr in self.document.getiterator('tr'): if not 'LGNTableRow' in tr.attrib.get('class', '').split(): continue account = Account() for td in tr.getiterator('td'): if td.attrib.get('headers', '') == 'TypeCompte': a = td.find('a') if a is None: break account.label = unicode(a.find("span").text) for pattern, actype in self.TYPES.iteritems(): if account.label.startswith(pattern): account.type = actype account._link_id = a.get('href', '') elif td.attrib.get('headers', '') == 'NumeroCompte': id = td.text id = id.replace(u'\xa0','') account.id = id elif td.attrib.get('headers', '') == 'Libelle': pass elif td.attrib.get('headers', '') == 'Solde': div = td.xpath('./div[@class="Solde"]') if len(div) > 0: balance = self.parser.tocleanstring(div[0]) if len(balance) > 0 and balance not in ('ANNULEE', 'OPPOSITION'): try: account.balance = Decimal(FrenchTransaction.clean_amount(balance)) except InvalidOperation: raise BrokenPageError('Unable to parse balance %r' % balance) account.currency = account.get_currency(balance) else: account.balance = NotAvailable if not account.label or empty(account.balance): continue if 'CARTE_' in account._link_id: ac = accounts[0] ac._card_links.append(account._link_id) if not ac.coming: ac.coming = Decimal('0.0') ac.coming += account.balance else: account._card_links = [] accounts.append(account) return iter(accounts)
def get_list(self): accounts = [] for tr in self.document.xpath('//table[@class="compteTable"]/tr'): if not tr.attrib.get('class', '').startswith('ligne_'): continue cols = tr.findall('td') if len(cols) < 2: continue try: amount = sum([Decimal(FrenchTransaction.clean_amount(txt)) for txt in cols[-1].itertext() if len(txt.strip()) > 0]) except InvalidOperation: continue a = cols[0].find('a') if a is None: # this line is a cards line. attach it on the first account. if len(accounts) == 0: self.logger.warning('There is a card link but no accounts!') continue for a in cols[0].xpath('.//li/a'): args = self.js2args(a.attrib['href']) if not 'numero_compte' in args or not 'numero_poste' in args: self.logger.warning('Card link with strange args: %s' % args) continue accounts[0]._card_links.append('%s.%s' % (args['numero_compte'], args['numero_poste'])) if not accounts[0].coming: accounts[0].coming = Decimal('0.0') accounts[0].coming += amount continue args = self.js2args(a.attrib['href']) if not 'numero_compte' in args or not 'numero_poste' in args: self.logger.warning('Account link for %r with strange args: %s' % (a.attrib.get('alt', a.text), args)) continue account = Account() account.id = u'%s.%s' % (args['numero_compte'], args['numero_poste']) account.label = to_unicode(a.attrib.get('alt', a.text.strip())) account.balance = amount account.currency = [account.get_currency(txt) for txt in cols[-1].itertext() if len(txt.strip()) > 0][0] account._card_links = [] accounts.append(account) return accounts
def get_list(self): accounts = [] for tr in self.document.getiterator('tr'): if not 'LGNTableRow' in tr.attrib.get('class', '').split(): continue account = Account() for td in tr.getiterator('td'): if td.attrib.get('headers', '') == 'TypeCompte': a = td.find('a') if a is None: break account.label = unicode(a.find("span").text) account._link_id = a.get('href', '') elif td.attrib.get('headers', '') == 'NumeroCompte': id = td.text id = id.replace(u'\xa0','') account.id = id elif td.attrib.get('headers', '') == 'Libelle': pass elif td.attrib.get('headers', '') == 'Solde': div = td.xpath('./div[@class="Solde"]') if len(div) > 0: balance = self.parser.tocleanstring(div[0]) if len(balance) > 0 and balance not in ('ANNULEE', 'OPPOSITION'): try: account.balance = Decimal(FrenchTransaction.clean_amount(balance)) except InvalidOperation: raise BrokenPageError('Unable to parse balance %r' % balance) account.currency = account.get_currency(balance) else: account.balance = NotAvailable if not account.label or empty(account.balance): continue if 'CARTE_' in account._link_id: ac = accounts[0] ac._card_links.append(account._link_id) if not ac.coming: ac.coming = Decimal('0.0') ac.coming += account.balance else: account._card_links = [] accounts.append(account) return iter(accounts)
def get_accounts_list(self): for tr in self.document.xpath('//div[@class="comptestabl"]/table/tbody/tr'): cols = tr.findall('td') link = cols[0].find('a') if link is None: continue a = Account() a.id, a.label = map(unicode, link.attrib['title'].split(' ', 1)) tmp_balance = self.parser.tocleanstring(cols[1]) a.currency = a.get_currency(tmp_balance) a.balance = Decimal(Transaction.clean_amount(tmp_balance)) a._card_links = [] a._link_id = link.attrib['href'] yield a
def parse_table(self, what, actype=Account.TYPE_UNKNOWN): tables = self.document.xpath("//table[@id='%s']" % what, smart_strings=False) if len(tables) < 1: return lines = tables[0].xpath(".//tbody/tr") for line in lines: account = Account() tmp = line.xpath("./td//a")[0] account.label = to_unicode(tmp.text) account.type = actype account._link_id = tmp.get("href") if 'BourseEnLigne' in account._link_id: account.type = Account.TYPE_MARKET tmp = line.xpath("./td/span/strong") if len(tmp) >= 2: tmp_id = tmp[0].text tmp_balance = tmp[1].text else: tmp_id = line.xpath("./td//span")[1].text tmp_balance = tmp[0].text account.id = tmp_id account.currency = account.get_currency(tmp_balance) account.balance = Decimal( FrenchTransaction.clean_amount(tmp_balance)) if account.id in self.accounts: a = self.accounts[account.id] a._card_links.append(account._link_id) if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance else: account._card_links = [] self.accounts[account.id] = account page = self.browser.get_page( self.browser.openurl( self.browser.buildurl( '/voscomptes/canalXHTML/comptesCommun/imprimerRIB/init-imprimer_rib.ea', ('compte.numero', account.id)))) account.iban = page.get_iban()
def get_list(self): accounts = OrderedDict() for tr in self.document.getiterator('tr'): first_td = tr.getchildren()[0] if (first_td.attrib.get('class', '') == 'i g' or first_td.attrib.get('class', '') == 'p g') \ and first_td.find('a') is not None: a = first_td.find('a') link = a.get('href', '') if link.startswith('POR_SyntheseLst'): continue url = urlparse(link) p = parse_qs(url.query) if not 'rib' in p: continue for i in (2,1): balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text.strip(' EUR')) if len(balance) > 0: break balance = Decimal(balance) id = p['rib'][0] if id in accounts: account = accounts[id] if not account.coming: account.coming = Decimal('0.0') account.coming += balance account._card_links.append(link) continue account = Account() account.id = id account.label = unicode(a.text).strip().lstrip(' 0123456789').title() account._link_id = link account._card_links = [] account.balance = balance accounts[account.id] = account return accounts.itervalues()
def get_list(self): account = None for cpt in self.document.xpath( '//a[@class="synthese_id_compte" or @class="synthese_carte_differe"]' ): url_to_parse = cpt.xpath('@href')[0].replace("\n", "") # link # account._link_id = lien vers historique d'un compte (courant ou livret) if '/mes-comptes/livret/' in url_to_parse: compte_id_re = re.compile(r'.*\?(.*)$') link_id = '/fr/prive/mes-comptes/livret/consulter-situation/consulter-solde.jsp?%s' % \ (compte_id_re.search(url_to_parse).groups()[0]) else: link_id = url_to_parse number = cpt.xpath('./span[@class="synthese_numero_compte"]') if len(number) == 0: account._card_links.append(link_id) continue account = Account() account.id = self.parser.tocleanstring(number[0]).replace( u'N°', '') try: balance = self.parser.tocleanstring( cpt.xpath('./span[contains(@class, "synthese_solde")]')[0]) except IndexError: continue account.balance = Decimal(Transaction.clean_amount(balance)) account.currency = account.get_currency(balance) account._link_id = link_id account._card_links = [] account.label = (' '.join([ CleanText.clean(part) for part in cpt.xpath('./text()') ])).strip(' - ').strip() for pattern, type in self.ACCOUNT_TYPES.iteritems(): if pattern in account._link_id: account.type = type yield account
def get_list(self): accounts = [] for tr in self.document.getiterator('tr'): tds = tr.findall('td') if len(tds) != 3 or tds[0].find('a') is None or tds[0].find('a').attrib.get('class', '') != 'flecheM': continue account = Account() account.id = tds[1].text.strip() a = tds[0].findall('a')[-1] account.label = unicode(a.text.strip()) account._link_id = a.attrib['href'] balance = u''.join([txt.strip() for txt in tds[2].itertext()]) account.balance = Decimal(FrenchTransaction.clean_amount(balance)) # check account type m = re.search('(\w+)_IdPrestation', account._link_id) account_type = None if m: account_type = m.group(1) if account_type != 'CPT': account.id += '.%s' % account_type if account_type == 'CB': accounts[0]._card_links.append(account._link_id) if not accounts[0].coming: accounts[0].coming = Decimal('0.0') accounts[0].coming += account.balance continue if account_type != 'CPT': # Don't support other kind of account histories. account._link_id = None account.currency = account.get_currency(tds[1].text) account._card_links = [] accounts.append(account) return iter(accounts)
def parse_table(self, what, actype=Account.TYPE_UNKNOWN): tables = self.document.xpath("//table[@id='%s']" % what, smart_strings=False) if len(tables) < 1: return lines = tables[0].xpath(".//tbody/tr") for line in lines: account = Account() tmp = line.xpath("./td//a")[0] account.label = to_unicode(tmp.text) account.type = actype account._link_id = tmp.get("href") if 'BourseEnLigne' in account._link_id: account.type = Account.TYPE_MARKET tmp = line.xpath("./td/span/strong") if len(tmp) >= 2: tmp_id = tmp[0].text tmp_balance = tmp[1].text else: tmp_id = line.xpath("./td//span")[1].text tmp_balance = tmp[0].text account.id = tmp_id account.currency = account.get_currency(tmp_balance) account.balance = Decimal(FrenchTransaction.clean_amount(tmp_balance)) if account.id in self.accounts: a = self.accounts[account.id] a._card_links.append(account._link_id) if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance else: account._card_links = [] self.accounts[account.id] = account page = self.browser.get_page(self.browser.openurl(self.browser.buildurl('/voscomptes/canalXHTML/comptesCommun/imprimerRIB/init-imprimer_rib.ea', ('compte.numero', account.id)))) account.iban = page.get_iban()
def get_list(self): accounts = [] for tr in self.document.getiterator('tr'): if not 'LGNTableRow' in tr.attrib.get('class', '').split(): continue account = Account() for td in tr.getiterator('td'): if td.attrib.get('headers', '') == 'TypeCompte': a = td.find('a') account.label = unicode(a.find("span").text) account._link_id = a.get('href', '') elif td.attrib.get('headers', '') == 'NumeroCompte': id = td.text id = id.replace(u'\xa0','') account.id = id elif td.attrib.get('headers', '') == 'Libelle': pass elif td.attrib.get('headers', '') == 'Solde': balance = td.find('div').text if balance != None: balance = balance.replace(u'\xa0','').replace(',','.') account.balance = Decimal(balance) else: account.balance = Decimal(0) if 'CARTE_' in account._link_id: ac = accounts[0] ac._card_links.append(account._link_id) if not ac.coming: ac.coming = Decimal('0.0') ac.coming += account.balance else: account._card_links = [] accounts.append(account) return iter(accounts)
def get_accounts_list(self): for table in self.document.xpath('//div[@class="comptestabl"]/table'): try: account_type = self.ACCOUNT_TYPES[table.xpath('./caption/text()')[0].strip()] except (IndexError,KeyError): account_type = Account.TYPE_UNKNOWN for tr in table.xpath('./tbody/tr'): cols = tr.findall('td') link = cols[0].find('a') if link is None: continue a = Account() a.type = account_type a.id, a.label = map(unicode, link.attrib['title'].split(' ', 1)) tmp_balance = self.parser.tocleanstring(cols[1]) a.currency = a.get_currency(tmp_balance) a.balance = Decimal(Transaction.clean_amount(tmp_balance)) a._card_links = [] a._link_id = link.attrib['href'] yield a
def parse_table(self, what, actype=Account.TYPE_UNKNOWN): tables = self.document.xpath("//table[@id='%s']" % what, smart_strings=False) if len(tables) < 1: return lines = tables[0].xpath(".//tbody/tr") for line in lines: account = Account() tmp = line.xpath("./td//a")[0] account.label = to_unicode(tmp.text) account.type = actype account._link_id = tmp.get("href") if 'BourseEnLigne' in account._link_id: account.type = Account.TYPE_MARKET tmp = line.xpath("./td/span/strong") if len(tmp) >= 2: tmp_id = tmp[0].text tmp_balance = tmp[1].text else: tmp_id = line.xpath("./td//span")[1].text tmp_balance = tmp[0].text account.id = tmp_id account.currency = account.get_currency(tmp_balance) account.balance = Decimal( FrenchTransaction.clean_amount(tmp_balance)) if account.id in self.accounts: a = self.accounts[account.id] a._card_links.append(account._link_id) if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance else: account._card_links = [] self.accounts[account.id] = account
def get_list(self): account = None for cpt in self.document.xpath('//a[@class="synthese_id_compte" or @class="synthese_carte_differe"]'): url_to_parse = cpt.xpath('@href')[0].replace("\n", "") # link # account._link_id = lien vers historique d'un compte (courant ou livret) if '/mes-comptes/livret/' in url_to_parse: compte_id_re = re.compile(r'.*\?(.*)$') link_id = '/fr/prive/mes-comptes/livret/consulter-situation/consulter-solde.jsp?%s' % \ (compte_id_re.search(url_to_parse).groups()[0]) else: link_id = url_to_parse number = cpt.xpath('./span[@class="synthese_numero_compte"]') if len(number) == 0: account._card_links.append(link_id) continue account = Account() account.id = self.parser.tocleanstring(number[0]).replace(u'N°', '') try: balance = self.parser.tocleanstring(cpt.xpath('./span[contains(@class, "synthese_solde")]')[0]) except IndexError: continue account.balance = Decimal(Transaction.clean_amount(balance)) account.currency = account.get_currency(balance) account._link_id = link_id account._card_links = [] account.label = (' '.join([CleanText.clean(part) for part in cpt.xpath('./text()')])).strip(' - ').strip() for pattern, type in self.ACCOUNT_TYPES.iteritems(): if pattern in account._link_id: account.type = type yield account
def _add_account(self, accounts, link, label, account_type, balance): info = self._get_account_info(link, accounts) if info is None: self.logger.warning('Unable to parse account %r: %r' % (label, link)) return account = Account() account.id = info['id'] if is_rib_valid(info['id']): account.iban = rib2iban(info['id']) account._info = info account.label = label account.type = self.ACCOUNT_TYPES.get( label, info['acc_type'] if 'acc_type' in info else account_type) balance = balance or self.get_balance(account) account.balance = Decimal( FrenchTransaction.clean_amount(balance) ) if balance and balance is not NotAvailable else NotAvailable account.currency = account.get_currency( balance ) if balance and balance is not NotAvailable else NotAvailable account._card_links = [] if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts: a = accounts[account.id] if not a.coming: a.coming = Decimal('0.0') if account.balance and account.balance is not NotAvailable: a.coming += account.balance a._card_links.append(account._info) return accounts[account.id] = account
def get_accounts_list(self): for table in self.document.xpath('//div[@class="comptestabl"]/table'): try: account_type = self.ACCOUNT_TYPES[table.xpath( './caption/text()')[0].strip()] except (IndexError, KeyError): account_type = Account.TYPE_UNKNOWN for tr in table.xpath('./tbody/tr'): cols = tr.findall('td') link = cols[0].find('a') if link is None: continue a = Account() a.type = account_type a.id, a.label = map(unicode, link.attrib['title'].split(' ', 1)) tmp_balance = self.parser.tocleanstring(cols[1]) a.currency = a.get_currency(tmp_balance) a.balance = Decimal(Transaction.clean_amount(tmp_balance)) a._card_links = [] a._link_id = link.attrib['href'] yield a
def get_list(self): accounts = [] for tr in self.document.xpath('//table[@class="compteTable"]/tr'): if not tr.attrib.get('class', '').startswith('ligne_'): continue cols = tr.findall('td') if len(cols) < 2: continue try: amount = sum([ Decimal(FrenchTransaction.clean_amount(txt)) for txt in cols[-1].itertext() if len(txt.strip()) > 0 ]) except InvalidOperation: continue a = cols[0].find('a') if a is None: # this line is a cards line. attach it on the first account. if len(accounts) == 0: self.logger.warning( 'There is a card link but no accounts!') continue for a in cols[0].xpath('.//li/a'): args = self.js2args(a.attrib['href']) if not 'numero_compte' in args or not 'numero_poste' in args: self.logger.warning('Card link with strange args: %s' % args) continue accounts[0]._card_links.append( '%s.%s' % (args['numero_compte'], args['numero_poste'])) if not accounts[0].coming: accounts[0].coming = Decimal('0.0') accounts[0].coming += amount continue args = self.js2args(a.attrib['href']) if not 'numero_compte' in args or not 'numero_poste' in args: self.logger.warning( 'Account link for %r with strange args: %s' % (a.attrib.get('alt', a.text), args)) continue account = Account() account.id = u'%s.%s' % (args['numero_compte'], args['numero_poste']) account.label = to_unicode(a.attrib.get('alt', a.text.strip())) account.balance = amount account.currency = [ account.get_currency(txt) for txt in cols[-1].itertext() if len(txt.strip()) > 0 ][0] account._card_links = [] accounts.append(account) return accounts
def get_list(self): accounts = [] for block in self.document.xpath('//div[@class="pave"]/div'): head_type = block.xpath('./div/span[@class="accGroupLabel"]')[0].text.strip() account_type = self.ACCOUNT_TYPES.get(head_type, Account.TYPE_UNKNOWN) for tr in block.cssselect('ul li.tbord_account'): id = tr.attrib.get('id', '') if id.find('contratId') != 0: self.logger.warning('Unable to parse contract ID: %r' % id) continue id = id[id.find('contratId')+len('contratId'):] link = tr.cssselect('span.accountLabel a')[0] balance = Decimal(FrenchTransaction.clean_amount(tr.cssselect('span.accountTotal')[0].text)) if id.endswith('CRT'): account = accounts[-1] account._card_links.append(link.attrib['href']) if not account.coming: account.coming = Decimal('0.0') account.coming += balance continue account = Account() account.id = id account.label = unicode(link.text.strip()) account.type = account_type account.balance = balance account.currency = account.get_currency(tr.cssselect('span.accountDev')[0].text) account._link = link.attrib['href'] account._card_links = [] accounts.append(account) if len(accounts) == 0: # Sometimes, accounts are only in javascript... for script in self.document.xpath('//script'): text = script.text if text is None: continue if 'remotePerso' not in text: continue account = None card_account = None attribs = {} account_type = Account.TYPE_UNKNOWN for line in text.split('\n'): line = line.strip() m = re.match("data.libelle = '(.*)';", line) if m: account_type = self.ACCOUNT_TYPES.get(m.group(1), Account.TYPE_UNKNOWN) elif line == 'var remotePerso = new Object;': account = Account() elif account is not None: m = re.match("remotePerso.(\w+) = '?(.*?)'?;", line) if m: attribs[m.group(1)] = m.group(2) elif line.startswith('listProduitsGroup'): account.id = attribs['refContrat'] account.label = attribs['libelle'] account.type = account_type account.balance = Decimal(FrenchTransaction.clean_amount(attribs['soldeDateOpeValeurFormatted'])) account.currency = account.get_currency(attribs['codeDevise']) account._link = 'tbord.do?id=%s&%s' % (attribs['id'], self.browser.SESSION_PARAM) account._card_links = [] if account.id.endswith('CRT'): if not len(accounts): card_account = account else: a = accounts[-1] a._card_links.append(account._link) if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance else: if 'COURANT' in account.label: account.type = account.TYPE_CHECKING elif account.id.endswith('TTR'): account.type = account.TYPE_MARKET elif re.match('^\d+C$', account.id): account.type = account.TYPE_LIFE_INSURANCE elif re.match('^\d+PRT$', account.id): account.type = account.TYPE_LOAN elif not account.type: account.type = account.TYPE_SAVINGS if card_account: account._card_links.append(card_account._link) if not account.coming: account.coming = Decimal('0.0') account.coming += card_account.balance card_account = None accounts.append(account) account = None return accounts
def get_list(self): accounts = [] for cpt in self.doc.xpath( '//div[contains(@class, " compte") and not(contains(@class, "compte_selected"))]' ): # ignore auto assurance accounts if 'aut' in cpt.get('class'): continue account = Account() account._history_link = Link( './ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) # this is to test if there is a redirection to a form for recently created profiles if len(accounts) == 0: message = self.browser.open( account._history_link).page.doc.xpath( '//div[@id="as_renouvellementMIFID.do_"]') if message: raise ActionNeeded( CleanText('./div[contains(text(), "Bonjour")]')( message[0])) number = RawText('./a[contains(@class, "numero_compte")]')( cpt).replace(u'N° ', '') account.id = CleanText(None).filter(number).replace(u'N°', '') account._card_links = [] card_link = Link('./ul/li/a[contains(text(), "Carte bancaire")]', default='')(cpt) if len(card_link) > 0: account._card_links.append(card_link) account.label = CleanText( './a[contains(@class, "numero_compte")]/@title')(cpt) for pattern, type in self.ACCOUNT_TYPES.iteritems(): if pattern in account._history_link: account.type = type break if account.type in { Account.TYPE_PEA, Account.TYPE_MARKET, Account.TYPE_LIFE_INSURANCE }: account._investment_link = Link( './ul/li/a[contains(@id, "portefeuille")]')(cpt) balance = self.browser.open( account._investment_link).page.get_balance(account.type) if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}: self.browser.cache["investments"][account.id] = list( self.browser.open( account._investment_link).page.get_investments( account)) else: balance = self.browser.open( account._history_link).page.get_balance() if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}: account.currency = self.browser.open( account._investment_link).page.get_currency() else: account.currency = account.get_currency(balance) account.balance = CleanDecimal(None, replace_dots=True).filter(balance) if account.type in (Account.TYPE_CHECKING, Account.TYPE_SAVINGS): # Need a token sent by SMS to customers account.iban = NotAvailable if (account.label, account.id, account.balance) not in [ (a.label, a.id, a.balance) for a in accounts ]: accounts.append(account) return iter(accounts)
def get_list(self): accounts = OrderedDict() for tr in self.document.getiterator('tr'): first_td = tr.getchildren()[0] if (first_td.attrib.get('class', '') == 'i g' or first_td.attrib.get('class', '') == 'p g') \ and first_td.find('a') is not None: a = first_td.find('a') link = a.get('href', '') if link.startswith('POR_SyntheseLst'): continue url = urlparse(link) p = parse_qs(url.query) if not 'rib' in p: continue for i in (2, 1): balance = FrenchTransaction.clean_amount( tr.getchildren()[i].text) currency = Account.get_currency(tr.getchildren()[i].text) if len(balance) > 0: break balance = Decimal(balance) id = p['rib'][0] if id in accounts: account = accounts[id] if not account.coming: account.coming = Decimal('0.0') account.coming += balance account._card_links.append(link) continue account = Account() account.id = id account.label = unicode( a.text).strip().lstrip(' 0123456789').title() account._link_id = link account._card_links = [] # Find accounting amount page = self.browser.get_document(self.browser.openurl(link)) coming = self.find_amount(page, u"Opérations à venir") accounting = self.find_amount(page, u"Solde comptable") if accounting is not None and accounting + ( coming or Decimal('0')) != balance: self.logger.warning('%s + %s != %s' % (accounting, coming, balance)) if accounting is not None: balance = accounting if coming is not None: account.coming = coming account.balance = balance account.currency = currency accounts[account.id] = account return accounts.itervalues()
def get_list(self): accounts = [] for cpt in self.doc.xpath('//div[contains(@class, " compte") and not(contains(@class, "compte_selected"))]'): # ignore auto assurance accounts if 'aut' in cpt.get('class'): continue account = Account() account._history_link = Link('./ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "contrat") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) # this is to test if access to the accounts info is blocked for different reasons page = self.browser.open(account._history_link).page if isinstance(page, LoanPage): account = Loan() account._history_link = Link('./ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "contrat") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) if isinstance(page, LoanPage): account.id = CleanText('(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]')(cpt) account.label = CleanText('(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]')(cpt) account.type = Account.TYPE_LOAN account_history_page = page account.total_amount = account_history_page.get_total_amount() account.next_payment_amount = account_history_page.get_next_payment_amount() account.next_payment_date = account_history_page.get_next_payment_date() account.account_label = account_history_page.get_account_label() account.subscription_date = account_history_page.get_subscription_date() account.maturity_date = account_history_page.get_maturity_date() if len(accounts) == 0: global_error_message = page.doc.xpath('//div[@id="as_renouvellementMIFID.do_"]/div[contains(text(), "Bonjour")] ' '| //div[@id="as_afficherMessageBloquantMigration.do_"]//div[@class="content_message"] ' '| //p[contains(text(), "Et si vous faisiez de Fortuneo votre banque principale")] ' '| //div[@id="as_renouvellementMotDePasse.do_"]//p[contains(text(), "votre mot de passe")]' '| //div[@id="as_afficherSecuriteForteOTPIdentification.do_"]//span[contains(text(), "Pour valider ")]') if global_error_message: raise ActionNeeded(CleanText('.')(global_error_message[0])) local_error_message = page.doc.xpath('//div[@id="error"]/p[@class="erreur_texte1"]') if local_error_message: raise BrowserUnavailable(CleanText('.')(local_error_message[0])) number = RawText('./a[contains(@class, "numero_compte")]')(cpt).replace(u'N° ', '') account.id = CleanText(None).filter(number).replace(u'N°', '') account._card_links = [] card_link = Link('./ul/li/a[contains(text(), "Carte bancaire")]', default='')(cpt) if len(card_link) > 0: account._card_links.append(card_link) account.label = CleanText('./a[contains(@class, "numero_compte")]/@title')(cpt) for pattern, type in self.ACCOUNT_TYPES.items(): if pattern in account._history_link: account.type = type break investment_page = None if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET, Account.TYPE_LIFE_INSURANCE}: account._investment_link = Link('./ul/li/a[contains(@id, "portefeuille")]')(cpt) investment_page = self.browser.open(account._investment_link).page balance = investment_page.get_balance(account.type) if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}: self.browser.investments[account.id] = list(self.browser.open(account._investment_link).page.get_investments(account)) else: balance = page.get_balance() if account.type is not Account.TYPE_LOAN: account.coming = page.get_coming() if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}: account.currency = investment_page.get_currency() else: account.currency = account.get_currency(balance) account.balance = CleanDecimal(None, replace_dots=True).filter(balance) if account.type in (Account.TYPE_CHECKING, Account.TYPE_SAVINGS): # Need a token sent by SMS to customers account.iban = NotAvailable if (account.label, account.id, account.balance) not in [(a.label, a.id, a.balance) for a in accounts]: accounts.append(account) return accounts
def get_list(self): accounts = [] for block in self.document.xpath('//div[@class="pave"]/div'): head_type = block.xpath( './div/span[@class="accGroupLabel"]')[0].text.strip() account_type = self.ACCOUNT_TYPES.get(head_type, Account.TYPE_UNKNOWN) for tr in block.cssselect('ul li.tbord_account'): id = tr.attrib.get('id', '') if id.find('contratId') != 0: self.logger.warning('Unable to parse contract ID: %r' % id) continue id = id[id.find('contratId') + len('contratId'):] link = tr.cssselect('span.accountLabel a')[0] balance = Decimal( FrenchTransaction.clean_amount( tr.cssselect('span.accountTotal')[0].text)) if id.endswith('CRT'): account = accounts[-1] account._card_links.append(link.attrib['href']) if not account.coming: account.coming = Decimal('0.0') account.coming += balance continue account = Account() account.id = id account.label = unicode(link.text.strip()) account.type = account_type account.balance = balance account.currency = account.get_currency( tr.cssselect('span.accountDev')[0].text) account._link = link.attrib['href'] account._card_links = [] accounts.append(account) if not accounts: # Sometimes, accounts are only in javascript... for script in self.document.xpath('//script'): text = script.text if text is None: continue if 'remotePerso' not in text: continue account = None attribs = {} account_type = Account.TYPE_UNKNOWN for line in text.split('\n'): line = line.strip() m = re.match("data.libelle = '(.*)';", line) if m: account_type = self.ACCOUNT_TYPES.get( m.group(1), Account.TYPE_UNKNOWN) elif line == 'var remotePerso = new Object;': account = Account() elif account is not None: m = re.match("remotePerso.(\w+) = '?(.*?)'?;", line) if m: attribs[m.group(1)] = m.group(2) elif line.startswith('listProduitsGroup'): account.id = attribs['refContrat'] account.label = attribs['libelle'] account.type = account_type account.balance = Decimal( FrenchTransaction.clean_amount( attribs['soldeDateOpeValeurFormatted'])) account.currency = account.get_currency( attribs['codeDevise']) account._link = 'tbord.do?id=%s' % attribs['id'] account._card_links = [] if account.id.endswith('CRT'): a = accounts[-1] a._card_links.append(account._link) if not a.coming: a.coming = Decimal('0.0') a.coming += account.balance else: accounts.append(account) account = None return accounts
def get_list(self): accounts = [] for cpt in self.doc.xpath( '//div[contains(@class, " compte") and not(contains(@class, "compte_selected"))]' ): # ignore auto assurance accounts if 'aut' in cpt.get('class'): continue account = Account() account._history_link = Link( './ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "contrat") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) # this is to test if access to the accounts info is blocked for different reasons page = self.browser.open(account._history_link).page if isinstance(page, LoanPage): account = Loan() account._history_link = Link( './ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "contrat") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) if isinstance(page, LoanPage): account.id = CleanText( '(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]' )(cpt) account.label = CleanText( '(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]' )(cpt) account.type = Account.TYPE_LOAN account_history_page = self.browser.open( account._history_link).page account.total_amount = account_history_page.get_total_amount() account.next_payment_amount = account_history_page.get_next_payment_amount( ) account.next_payment_date = account_history_page.get_next_payment_date( ) account.account_label = account_history_page.get_account_label( ) account.subscription_date = account_history_page.get_subscription_date( ) account.maturity_date = account_history_page.get_maturity_date( ) if len(accounts) == 0: global_error_message = page.doc.xpath( '//div[@id="as_renouvellementMIFID.do_"]/div[contains(text(), "Bonjour")] ' '| //div[@id="as_afficherMessageBloquantMigration.do_"]//div[@class="content_message"] ' '| //p[contains(text(), "Et si vous faisiez de Fortuneo votre banque principale")] ' '| //div[@id="as_renouvellementMotDePasse.do_"]//p[contains(text(), "votre mot de passe")]' '| //div[@id="as_afficherSecuriteForteOTPIdentification.do_"]//span[contains(text(), "Pour valider ")]' ) if global_error_message: raise ActionNeeded(CleanText('.')(global_error_message[0])) local_error_message = page.doc.xpath( '//div[@id="error"]/p[@class="erreur_texte1"]') if local_error_message: raise BrowserUnavailable( CleanText('.')(local_error_message[0])) number = RawText('./a[contains(@class, "numero_compte")]')( cpt).replace(u'N° ', '') account.id = CleanText(None).filter(number).replace(u'N°', '') account._card_links = [] card_link = Link('./ul/li/a[contains(text(), "Carte bancaire")]', default='')(cpt) if len(card_link) > 0: account._card_links.append(card_link) account.label = CleanText( './a[contains(@class, "numero_compte")]/@title')(cpt) for pattern, type in self.ACCOUNT_TYPES.items(): if pattern in account._history_link: account.type = type break if account.type in { Account.TYPE_PEA, Account.TYPE_MARKET, Account.TYPE_LIFE_INSURANCE }: account._investment_link = Link( './ul/li/a[contains(@id, "portefeuille")]')(cpt) balance = self.browser.open( account._investment_link).page.get_balance(account.type) if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}: self.browser.investments[account.id] = list( self.browser.open( account._investment_link).page.get_investments( account)) else: balance = self.browser.open( account._history_link).page.get_balance() if account.type is not Account.TYPE_LOAN: account.coming = self.browser.open( account._history_link).page.get_coming() if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}: account.currency = self.browser.open( account._investment_link).page.get_currency() else: account.currency = account.get_currency(balance) account.balance = CleanDecimal(None, replace_dots=True).filter(balance) if account.type in (Account.TYPE_CHECKING, Account.TYPE_SAVINGS): # Need a token sent by SMS to customers account.iban = NotAvailable if (account.label, account.id, account.balance) not in [ (a.label, a.id, a.balance) for a in accounts ]: accounts.append(account) return accounts
def get_list(self): accounts = [] for cpt in self.doc.xpath('//div[contains(@class, " compte") and not(contains(@class, "compte_selected"))]'): # ignore auto assurance accounts if 'aut' in cpt.get('class'): continue account = Account() account._history_link = Link('./ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "contrat") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) # this is to test if access to the accounts info is blocked for different reasons page = self.browser.open(account._history_link).page if isinstance(page, LoanPage): account = Loan() account._history_link = Link('./ul/li/a[contains(@id, "consulter_solde") ' 'or contains(@id, "historique") ' 'or contains(@id, "contrat") ' 'or contains(@id, "assurance_vie_operations")]')(cpt) if isinstance(page, LoanPage): account.id = CleanText('(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]')(cpt) account.label = CleanText('(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]')(cpt) account.type = Account.TYPE_LOAN account_history_page = page account.total_amount = account_history_page.get_total_amount() account.next_payment_amount = account_history_page.get_next_payment_amount() account.next_payment_date = account_history_page.get_next_payment_date() account.account_label = account_history_page.get_account_label() account.subscription_date = account_history_page.get_subscription_date() account.maturity_date = account_history_page.get_maturity_date() account.ownership = account_history_page.get_owner() if len(accounts) == 0: global_error_message = page.doc.xpath('//div[@id="as_renouvellementMIFID.do_"]/div[contains(text(), "Bonjour")] ' '| //div[@id="as_afficherMessageBloquantMigration.do_"]//div[@class="content_message"] ' '| //p[contains(text(), "Et si vous faisiez de Fortuneo votre banque principale")] ' '| //div[@id="as_renouvellementMotDePasse.do_"]//p[contains(text(), "votre mot de passe")]' '| //div[@id="as_afficherSecuriteForteOTPIdentification.do_"]//span[contains(text(), "Pour valider ")]') if global_error_message: if "Et si vous faisiez de Fortuneo votre banque principale" in CleanText(global_error_message)(self): self.browser.location('/ReloadContext', data={'action': 4}) return raise ActionNeeded(CleanText('.')(global_error_message[0])) local_error_message = page.doc.xpath('//div[@id="error"]/p[@class="erreur_texte1"]') if local_error_message: raise BrowserUnavailable(CleanText('.')(local_error_message[0])) account.id = account.number = CleanText('./a[contains(@class, "numero_compte")]/div')(cpt).replace(u'N° ', '') account._ca = CleanText('./a[contains(@class, "numero_compte")]/@rel')(cpt) account._card_links = [] card_link = Link('./ul/li/a[contains(text(), "Carte bancaire")]', default='')(cpt) if len(card_link) > 0: account._card_links.append(card_link) account.label = CleanText('./a[contains(@class, "numero_compte")]/@title')(cpt) for pattern, type in self.ACCOUNT_TYPES.items(): if pattern in account._history_link: account.type = type break investment_page = None if account.type in (Account.TYPE_PEA, Account.TYPE_MARKET, Account.TYPE_LIFE_INSURANCE): account._investment_link = Link('./ul/li/a[contains(@id, "portefeuille")]')(cpt) investment_page = self.browser.location(account._investment_link).page balance = investment_page.get_balance(account.type) if account.type in (Account.TYPE_PEA, Account.TYPE_MARKET): self.browser.investments[account.id] = list(self.browser.open(account._investment_link).page.get_investments(account)) else: balance = page.get_balance() if account.type is not Account.TYPE_LOAN: account.coming = page.get_coming() if account.type in (Account.TYPE_PEA, Account.TYPE_MARKET): account.currency = investment_page.get_currency() elif balance: account.currency = account.get_currency(balance) account.balance = CleanDecimal.French().filter(balance) if account.type in (Account.TYPE_CHECKING, Account.TYPE_SAVINGS): # Need a token sent by SMS to customers account.iban = NotAvailable if account.type is not Account.TYPE_LOAN: regexp = re.search(r'(m\. |mme\. )(.+)', CleanText('//span[has-class("mon_espace_nom")]')(self.doc), re.IGNORECASE) if regexp and len(regexp.groups()) == 2: gender = regexp.group(1).replace('.', '').rstrip() name = regexp.group(2) label = account.label if re.search(r'(m|mr|me|mme|mlle|mle|ml)\.? (.*)\bou (m|mr|me|mme|mlle|mle|ml)\b(.*)', label, re.IGNORECASE): account.ownership = AccountOwnership.CO_OWNER elif re.search(r'{} {}'.format(gender, name), label, re.IGNORECASE): account.ownership = AccountOwnership.OWNER else: account.ownership = AccountOwnership.ATTORNEY if (account.label, account.id, account.balance) not in [(a.label, a.id, a.balance) for a in accounts]: accounts.append(account) return accounts