def _parse_account(self, tr): account = Account() account.id = tr.xpath('.//td[@class="libelleCompte"]/input')[0].attrib['id'][len('libelleCompte'):] if len(str(account.id)) == 23: account.id = str(account.id)[5:21] a = tr.xpath('.//td[@class="libelleCompte"]/a')[0] m = re.match(r'javascript:goToStatements\(\'(\d+)\'', a.get('onclick', '')) if m: account._link_id = m.group(1) else: # Can't get history for this account. account._link_id = None # To prevent multiple-IDs for CIF (for example), add an arbitrary char in ID. account.id += 'C' account.label = u''+a.text.strip() tds = tr.findall('td') account.balance = self._parse_amount(tds[3].find('a')) if tds[4].find('a') is not None: account.coming = self._parse_amount(tds[4].find('a')) else: account.coming = NotAvailable return account
def get_list(self): table = self.find_table() for tr in self.parser.select(table, 'tr', 'many'): tds = self.parser.select(tr, 'td') if len(tds) != 6: continue tdlabel, tdid, tdcur, tdupdated, tdbal, tdbalcur = tds account = Account() account.label = to_unicode(tdlabel.text_content().strip()) # this is important - and is also the last part of the id (considering spaces) # we can't use only the link as it does not goes where we want try: link = self.parser.select(tdlabel, 'a', 1) except BrokenPageError: # probably an account we can't display the history account._link_id = None else: account._link_id = parse_qs(link.attrib['href'])['ch4'][0] account.id = to_unicode(tdid.text.strip().replace(' ', '')) account.iban = 'FR76' + account.id # just in case we are showing the converted balances account._main_currency = Account.get_currency(tdcur.text) # we have to ignore those accounts, because using NotAvailable # makes boobank and probably many others crash if tdbal.text_content().strip() == 'indisponible': continue account.balance = Decimal( Transaction.clean_amount(tdbal.text_content())) account.currency = Account.get_currency(tdbalcur.text) account._updated = datetime.strptime(tdupdated.text, '%d/%m/%Y') yield account
def get_list(self): 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 = a.text.strip() account._link_id = a.attrib['href'] m = re.search('(\w+)_IdPrestation', account._link_id) if not m or m.group(1) != 'CPT': account._link_id = None if m: account.id += '.%s' % m.group(1) tag = tds[2].find('font') if tag is None: tag = tds[2] account.balance = Decimal(tag.text.replace('.','').replace(',','.').replace(' ', '').strip(u' \t\u20ac\xa0€\n\r')) account.coming = NotAvailable yield account
def get_list(self): table = self.find_table() for tr in self.parser.select(table, 'tr', 'many'): tds = self.parser.select(tr, 'td') if len(tds) != 6: continue tdlabel, tdid, tdcur, tdupdated, tdbal, tdbalcur = tds account = Account() account.label = to_unicode(tdlabel.text_content().strip()) # this is important - and is also the last part of the id (considering spaces) # we can't use only the link as it does not goes where we want try: link = self.parser.select(tdlabel, 'a', 1) except BrokenPageError: # probably an account we can't display the history account._link_id = None else: account._link_id = parse_qs(link.attrib['href'])['ch4'][0] account.id = to_unicode(tdid.text.strip().replace(' ', '')) account.iban = 'FR76' + account.id # just in case we are showing the converted balances account._main_currency = Account.get_currency(tdcur.text) # we have to ignore those accounts, because using NotAvailable # makes boobank and probably many others crash if tdbal.text_content().strip() == 'indisponible': continue account.balance = Decimal(Transaction.clean_amount(tdbal.text_content())) account.currency = Account.get_currency(tdbalcur.text) account._updated = datetime.strptime(tdupdated.text, '%d/%m/%Y') yield account
def get_list(self): """ Returns the list of available bank accounts """ for div in self.document.getiterator('div'): if div.attrib.get('class', '') in ( 'dv', 'headline') and div.getchildren()[0].tag in ('a', 'br'): self.logger.debug("Analyzing div %s" % div) # Step 1: extract text tokens tokens = [] required_tokens = {} optional_tokens = {} token_extractor = TokenExtractor() for token in token_extractor.extract_tokens(div): self.logger.debug('Extracted text token: "%s"' % token) tokens.append(token) # Step 2: analyse tokens for token in tokens: if self.look_like_account_number(token): required_tokens['account_number'] = token elif self.look_like_amount(token): required_tokens['account_amount'] = token elif self.look_like_account_name(token): required_tokens['account_name'] = token elif self.look_like_account_owner(token): if 'account_owner' in optional_tokens and 'account_name' not in required_tokens: required_tokens['account_name'] = optional_tokens[ 'account_owner'] optional_tokens['account_owner'] = token # Step 3: create account objects if len(required_tokens) >= 3: account = Account() account.label = required_tokens['account_name'] account.id = required_tokens['account_number'] account.balance = FrenchTransaction.clean_amount( required_tokens['account_amount']) account.currency = account.get_currency( required_tokens['account_amount']) # we found almost all required information to create an account object self.logger.debug( 'Found account %s with number %s and balance = %.2f' % (account.label, account.id, account.balance)) # we may have found the owner name too if optional_tokens.get('account_owner') is not None: # well, we could add it to the label, but is this really required? self.logger.debug(' the owner appears to be %s' % optional_tokens['account_owner']) # we simply lack the link to the account history... which remains optional first_link = div.find('a') if first_link is not None: account._link_id = first_link.get('href') self.logger.debug( ' the history link appears to be %s' % account._link_id) else: account._link_id = None yield account
def get_list(self): for div in self.document.getiterator('div'): if div.attrib.get('id', '') == 'synthese-list': for tr in div.getiterator('tr'): account = Account() account.id = None account._link_id = None for td in tr.getiterator('td'): if td.attrib.get('class', '') == 'account-cb': break elif td.attrib.get('class', '') == 'account-name': try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) account._link_id = td.xpath( './/a')[0].attrib['href'] elif td.attrib.get('class', '') == 'account-more-actions': for a in td.getiterator('a'): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if "mouvements.phtml" in a.attrib[ 'href'] and "/cartes/" not in a.attrib[ 'href']: account._link_id = a.attrib['href'] elif td.attrib.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.attrib.get('class', '') == 'account-total': span = td.find('span') if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None: yield account
def get_list(self): for div in self.document.getiterator('div'): if div.attrib.get('id', '') == 'synthese-list': for tr in div.getiterator('tr'): account = Account() account.id = None account._link_id = None for td in tr.getiterator('td'): if td.attrib.get('class', '') == 'account-cb': break elif td.attrib.get('class', '') == 'account-name': try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) try: account._link_id = td.xpath('.//a')[0].attrib['href'] except KeyError: pass elif td.attrib.get('class', '') == 'account-more-actions': for a in td.getiterator('a'): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if "mouvements.phtml" in a.attrib['href'] and "/cartes/" not in a.attrib['href']: account._link_id = a.attrib['href'] elif td.attrib.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.attrib.get('class', '') == 'account-total': span = td.find('span') if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None: yield account
def get_list(self, accounts_ids): l = [] # Read the json data json_data = self.browser.readurl( '/banque/PA_Autonomy-war/ProxyIAService?cleOutil=IA_SMC_UDC&service=getlstcpt&dashboard=true&refreshSession=true&cre=udc&poka=true' ) json_infos = json.loads(json_data) for famille in json_infos['smc']['data']['familleCompte']: id_famille = famille['idFamilleCompte'] for compte in famille['compte']: account = Account() account.label = unicode(compte['libellePersoProduit'] or compte['libelleProduit']) account.currency = account.get_currency(compte['devise']) account.balance = Decimal(str(compte['soldeDispo'])) account.coming = Decimal(str(compte['soldeAVenir'])) account.type = self.ACCOUNT_TYPES.get(id_famille, Account.TYPE_UNKNOWN) account.id = None if account.type != Account.TYPE_LIFE_INSURANCE: account._link_id = 'KEY' + compte['key'] else: account._link_id = None # IBAN aren't in JSON # Fast method, get it from transfer page. for i, a in accounts_ids.items(): if a.label == account.label: account.id = i # But it's doesn't work with LOAN and MARKET, so use slow method : Get it from transaction page. if account.id is None: if account._link_id: self.logger.debug('Get IBAN for account %s', account.label) account.id = self.browser.get_IBAN_from_account( account) else: account.id = compte['value'] l.append(account) if len(l) == 0: self.logger.warning('no accounts') # oops, no accounts? check if we have not exhausted the allowed use # of this password for img in self.document.getroot().cssselect( 'img[align="middle"]'): if img.attrib.get('alt', '') == 'Changez votre code secret': raise BrowserPasswordExpired('Your password has expired') return l
def get_list(self): for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"): account = Account() # account.id account.id = ( cpt.xpath("./span[1]/text()")[0] .replace(u"\xa0", "") .replace(",", ".") .replace("EUR", "") .replace("\n", "") .replace("\t", "") .replace(u"\xb0", "") .replace(" ", "") .replace("N", "") ) # account balance account.balance = Decimal(Transaction.clean_amount(cpt.xpath("./span[2]/text()")[0])) account.currency = account.get_currency(cpt.xpath("./span[2]/text()")[0]) # account coming TODO # mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") # mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0] # mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") # if mycomingval == '-': # account.coming = Decimal(0) # else: # account.coming = Decimal(mycomingval) url_to_parse = cpt.xpath("@href")[0].replace("\n", "") # link # account._link_id = lien vers historique d'un compte (courant of livret) if "/mes-comptes/livret/" in url_to_parse: compte_id_re = re.compile(r".*\?(.*)$") account._link_id = "/fr/prive/mes-comptes/livret/consulter-situation/consulter-solde.jsp?%s" % ( compte_id_re.search(url_to_parse).groups()[0] ) else: account._link_id = url_to_parse # account.label account.label = cpt.xpath("./text()")[1].replace(u"-\xa0", "").replace("\n", "").replace("\t", "") for pattern, type in self.ACCOUNT_TYPES.iteritems(): if pattern in account._link_id: account.type = type yield account
def get_list(self): """ Returns the list of available bank accounts """ for div in self.document.getiterator('div'): if div.attrib.get('class', '') in ('dv', 'headline') and div.getchildren()[0].tag in ('a', 'br'): self.logger.debug("Analyzing div %s" % div) # Step 1: extract text tokens tokens = [] required_tokens = {} optional_tokens = {} token_extractor = TokenExtractor() for token in token_extractor.extract_tokens(div): self.logger.debug('Extracted text token: "%s"' % token) tokens.append(token) # Step 2: analyse tokens for token in tokens: if self.look_like_account_number(token): required_tokens['account_number'] = token elif self.look_like_amount(token): required_tokens['account_amount'] = token elif self.look_like_account_name(token): required_tokens['account_name'] = token elif self.look_like_account_owner(token): if 'account_owner' in optional_tokens and not 'account_name' in required_tokens: required_tokens['account_name'] = optional_tokens['account_owner'] optional_tokens['account_owner'] = token # Step 3: create account objects if len(required_tokens) >= 3: account = Account() account.label = required_tokens['account_name'] account.id = required_tokens['account_number'] account.balance = FrenchTransaction.clean_amount(required_tokens['account_amount']) account.currency = account.get_currency(required_tokens['account_amount']) # we found almost all required information to create an account object self.logger.debug('Found account %s with number %s and balance = %.2f' % (account.label, account.id, account.balance)) # we may have found the owner name too if optional_tokens.get('account_owner') is not None: # well, we could add it to the label, but is this really required? self.logger.debug(' the owner appears to be %s' % optional_tokens['account_owner']) # we simply lack the link to the account history... which remains optional first_link = div.find('a') if first_link is not None: account._link_id = first_link.get('href') self.logger.debug(' the history link appears to be %s' % account._link_id) else: account._link_id = None yield account
def get_list(self, pro=True): accounts = [] for tr in self.document.xpath('//tr[@class="comptes"]'): cols = tr.findall('td') if len(cols) < 5: continue account = Account() account.id = self.parser.tocleanstring(cols[self.COL_ID]).replace( " ", "") account.label = self.parser.tocleanstring(cols[self.COL_LABEL]) account.balance = Decimal( self.parser.tocleanstring(cols[self.COL_BALANCE])) try: account.coming = Decimal( self.parser.tocleanstring(cols[self.COL_COMING])) except InvalidOperation: if self.parser.tocleanstring(cols[self.COL_COMING]) != '-': self.logger.warning('Unable to parse coming value', exc_info=True) account.coming = NotAvailable account._link_id = None account._stp = None a = cols[self.COL_LABEL].find('a') if a is not None: url = urlparse(a.attrib['href']) p = dict(parse_qsl(url.query)) account._link_id = p.get('ch4', None) account._stp = p.get('stp', None) accounts.append(account) # If there are also personnal accounts linked, display the page and iter on them. if pro and len( self.document.xpath( '//div[@class="onglets"]//a[contains(@href, "afficherComptesPrives")]' )) > 0: self.browser.select_form(name='myForm') self.browser.set_all_readonly(False) self.browser['udcAction'] = '/afficherComptesPrives' self.browser.submit() for a in self.browser.page.get_list(False): accounts.append(a) return accounts
def get_list(self): for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"): account = Account() # account.id account.id = cpt.xpath("./span[1]/text()")[0].replace( u"\xa0", "").replace(',', '.').replace("EUR", "").replace( "\n", "").replace("\t", "").replace(u"\xb0", '').replace(" ", "").replace('N', '') # account balance account.balance = Decimal( Transaction.clean_amount(cpt.xpath("./span[2]/text()")[0])) account.currency = account.get_currency( cpt.xpath("./span[2]/text()")[0]) # account coming TODO #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0] #mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") #if mycomingval == '-': # account.coming = Decimal(0) #else: # account.coming = Decimal(mycomingval) url_to_parse = cpt.xpath('@href')[0].replace("\n", "") # link # account._link_id = lien vers historique d'un compte (courant of livret) if '/mes-comptes/livret/' in url_to_parse: compte_id_re = re.compile(r'.*\?(.*)$') account._link_id = '/fr/prive/mes-comptes/livret/consulter-situation/consulter-solde.jsp?%s' % \ (compte_id_re.search(url_to_parse).groups()[0]) else: account._link_id = url_to_parse # account.label account.label = cpt.xpath('./text()')[1].replace( u'-\xa0', '').replace("\n", "").replace("\t", "") for pattern, type in self.ACCOUNT_TYPES.iteritems(): if pattern in account._link_id: account.type = type yield account
def get_list(self, accounts_ids): l = [] # Read the json data json_data = self.browser.readurl('/banque/PA_Autonomy-war/ProxyIAService?cleOutil=IA_SMC_UDC&service=getlstcpt&dashboard=true&refreshSession=true&cre=udc&poka=true') json_infos = json.loads(json_data) for famille in json_infos['smc']['data']['familleCompte']: id_famille = famille['idFamilleCompte'] for compte in famille['compte']: account = Account() account.label = u''+compte['libellePersoProduit'] account.currency = account.get_currency(compte['devise']) account.balance = Decimal(str(compte['soldeDispo'])) account.coming = Decimal(str(compte['soldeAVenir'])) account.type = self.ACCOUNT_TYPES.get(id_famille, Account.TYPE_UNKNOWN) account.id = 0 account._link_id = 'KEY'+compte['key'] # IBAN aren't in JSON # Fast method, get it from transfer page. for i,a in accounts_ids.items(): if a.label == account.label: account.id = i # But it's doesn't work with LOAN and MARKET, so use slow method : Get it from transaction page. if account.id == 0: account.id = self.browser.get_IBAN_from_account(account) l.append(account) if len(l) == 0: print 'no accounts' # oops, no accounts? check if we have not exhausted the allowed use # of this password for img in self.document.getroot().cssselect('img[align="middle"]'): if img.attrib.get('alt', '') == 'Changez votre code secret': raise BrowserPasswordExpired('Your password has expired') return l
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 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.balance = Decimal(''.join( tmp_balance.replace('.', '').replace(',', '.').split())) self.account_list.append(account)
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.balance = Decimal("".join(tmp_balance.replace(".", "").replace(",", ".").split())) self.account_list.append(account)
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 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, pro=True): accounts = [] for tr in self.document.xpath('//tr[@class="comptes"]'): cols = tr.findall('td') if len(cols) < 5: continue account = Account() account.id = self.parser.tocleanstring(cols[self.COL_ID]).replace(" ", "") account.label = self.parser.tocleanstring(cols[self.COL_LABEL]) account.balance = Decimal(self.parser.tocleanstring(cols[self.COL_BALANCE])) try: account.coming = Decimal(self.parser.tocleanstring(cols[self.COL_COMING])) except InvalidOperation: if self.parser.tocleanstring(cols[self.COL_COMING]) != '-': self.logger.warning('Unable to parse coming value', exc_info=True) account.coming = NotAvailable account._link_id = None account._stp = None a = cols[self.COL_LABEL].find('a') if a is not None: url = urlparse(a.attrib['href']) p = dict(parse_qsl(url.query)) account._link_id = p.get('ch4', None) account._stp = p.get('stp', None) for input_tag in tr.xpath('.//input[starts-with(@id, "urlRib")]'): m = re.search('ch4=(\w+)', input_tag.get('value', '')) if m: account.iban = unicode(m.group(1)) accounts.append(account) # If there are also personnal accounts linked, display the page and iter on them. if pro and len(self.document.xpath('//div[@class="onglets"]//a[contains(@href, "afficherComptesPrives")]')) > 0: self.browser.select_form(name='myForm') self.browser.set_all_readonly(False) self.browser['udcAction'] = '/afficherComptesPrives' self.browser.submit() for a in self.browser.page.get_list(False): accounts.append(a) return accounts
def get_list(self): l = [] ids = set() for a in self.document.getiterator('a'): link = a.attrib.get('href') if link is None: continue if link.startswith("/outil/UWLM/ListeMouvements"): account = Account() account._link_id = link + "&mode=45" account._coming_links = [] parameters = link.split("?").pop().split("&") for parameter in parameters: list = parameter.split("=") value = list.pop() name = list.pop() if name == "agence": account.id = value elif name == "compte": account.id += value elif name == "nature": # TODO parse this string to get the right Account.TYPE_* to # store in account.type. account._type = value if account.id in ids: continue ids.add(account.id) div = a.getparent().getprevious() if not div.text.strip(): div = div.find('div') account.label = u'' + div.text.strip() balance = FrenchTransaction.clean_amount(a.text) if '-' in balance: balance = '-' + balance.replace('-', '') account.balance = Decimal(balance) account.currency = account.get_currency(a.text) self.logger.debug('%s Type: %s' % (account.label, account._type)) l.append(account) if link.startswith('/outil/UWCB/UWCBEncours'): if len(l) == 0: self.logger.warning( 'There is a card account but not any check account') continue account = l[-1] coming = FrenchTransaction.clean_amount(a.text) if '-' in coming: coming = '-' + coming.replace('-', '') if not account.coming: account.coming = Decimal('0') account.coming += Decimal(coming) account._coming_links.append(link) return l
def get_list(self): l = [] ids = set() for a in self.document.getiterator('a'): link=a.attrib.get('href') if link is None: continue if link.startswith("/outil/UWLM/ListeMouvements"): account = Account() #by default the website propose the last 7 days or last 45 days but we can force to have the last 55days account._link_id=link+"&mode=55" account._coming_links = [] parameters=link.split("?").pop().split("&") for parameter in parameters: list=parameter.split("=") value=list.pop() name=list.pop() if name=="agence": account.id=value elif name=="compte": account.id+=value elif name=="nature": # TODO parse this string to get the right Account.TYPE_* to # store in account.type. account._type=value if account.id in ids: continue ids.add(account.id) div = a.getparent().getprevious() if not div.text.strip(): div = div.find('div') account.label=u''+div.text.strip() balance = FrenchTransaction.clean_amount(a.text) if '-' in balance: balance='-'+balance.replace('-', '') account.balance=Decimal(balance) account.currency = account.get_currency(a.text) self.logger.debug('%s Type: %s' % (account.label, account._type)) l.append(account) if link.startswith('/outil/UWCB/UWCBEncours'): if len(l) == 0: self.logger.warning('There is a card account but not any check account') continue account = l[-1] coming = FrenchTransaction.clean_amount(a.text) if '-' in coming: coming = '-'+coming.replace('-', '') if not account.coming: account.coming = Decimal('0') account.coming += Decimal(coming) account._coming_links.append(link) return l
def get_list(self): l = [] for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"): account = Account() # account.id account.id = ( cpt.xpath("./span[1]/text()")[0] .replace(u"\xa0", "") .replace(",", ".") .replace("EUR", "") .replace("\n", "") .replace("\t", "") .replace(u"\xb0", "") .replace(" ", "") .replace("N", "") ) # account balance account.balance = Decimal( cpt.xpath("./span[2]/text()")[0] .replace("+", "") .replace(u"\xa0", "") .replace(",", ".") .replace("EUR", "") .replace("\n", "") .replace("\t", "") .replace(" ", "") ) # account coming TODO # mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") # mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0] # mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") # if mycomingval == '-': # account.coming = Decimal(0) # else: # account.coming = Decimal(mycomingval) # account._link_id url_to_parse = cpt.xpath("@href")[0].replace("\n", "") # link compte_id_re = re.compile(r"/prive/mes-comptes/([^/]+/).*COMPTE_ACTIF=([^\&]+)\&?") account._link_id = "/fr/prive/mes-comptes/%sconsulter-situation/consulter-solde.jsp?COMPTE_ACTIF=%s" % ( compte_id_re.search(url_to_parse).groups()[0], compte_id_re.search(url_to_parse).groups()[1], ) # account.label temp_label = cpt.xpath("./text()")[1].replace(u"-\xa0", "").replace("\n", "").replace("\t", "") account.label = " ".join(temp_label.split(" ")[:2]) l.append(account) return l
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 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): for tr in self.document.getiterator('tr'): if 'LGNTableRow' not 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 = self.parser.tocleanstring(a) 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': account.id = self.parser.tocleanstring(td).replace( u'\xa0', '') elif td.attrib.get('headers', '') == 'Libelle': text = self.parser.tocleanstring(td) if text != '': account.label = text 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: account.type = account.TYPE_CARD account.coming = account.balance account.balance = Decimal('0') yield account
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_list(self): l = [] for a in self.document.getiterator('a'): link=a.attrib.get('href') if link is None: continue if link.startswith("/outil/UWLM/ListeMouvements"): account = Account() account._link_id=link+"&mode=45" account._coming_links = [] parameters=link.split("?").pop().split("&") for parameter in parameters: list=parameter.split("=") value=list.pop() name=list.pop() if name=="agence": account.id=value elif name=="compte": account.id+=value elif name=="nature": # TODO parse this string to get the right Account.TYPE_* to # store in account.type. account._type=value div = a.getparent().getprevious() if not div.text.strip(): div = div.find('div') account.label=u''+div.text.strip() balance=a.text.replace(u"\u00A0",'').replace(' ','').replace('.','').replace('+','').replace(',','.').strip() if '-' in balance: balance='-'+balance.replace('-', '') account.balance=Decimal(balance) self.logger.debug('%s Type: %s' % (account.label, account._type)) l.append(account) if link.startswith('/outil/UWCB/UWCBEncours'): if len(l) == 0: self.logger.warning('There is a card account but not any check account') continue account = l[-1] coming = a.text.replace(u"\u00A0",'').replace(' ','').replace('.','').replace('+','').replace(',','.').strip() if '-' in coming: coming = '-'+coming.replace('-', '') if not account.coming: account.coming = Decimal('0') account.coming += Decimal(coming) account._coming_links.append(link) return l
def get_list(self): for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"): account = Account() # account.id account.id = cpt.xpath("./span[1]/text()")[0].replace(u"\xa0", "").replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xb0", '').replace(" ", "").replace('N', '') # account balance account.balance = Decimal(Transaction.clean_amount(cpt.xpath("./span[2]/text()")[0])) account.currency = account.get_currency(cpt.xpath("./span[2]/text()")[0]) # account coming TODO #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0] #mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") #if mycomingval == '-': # account.coming = Decimal(0) #else: # account.coming = Decimal(mycomingval) url_to_parse = cpt.xpath('@href')[0].replace("\n", "") # link # account._link_id = lien vers historique d'un compte (courant of livret) if '/mes-comptes/livret/' in url_to_parse: compte_id_re = re.compile(r'.*\?(.*)$') account._link_id = '/fr/prive/mes-comptes/livret/consulter-situation/consulter-solde.jsp?%s' % \ (compte_id_re.search(url_to_parse).groups()[0]) else: account._link_id = url_to_parse # account.label temp_label = cpt.xpath('./text()')[1].replace(u'-\xa0', '').replace("\n", "").replace("\t", "") account.label = " ".join(temp_label.split(" ")[:2]) yield account
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 get_list(self): for tr in self.document.getiterator('tr'): if 'LGNTableRow' not 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 = self.parser.tocleanstring(a) 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': account.id = self.parser.tocleanstring(td).replace(u'\xa0', '') elif td.attrib.get('headers', '') == 'Libelle': text = self.parser.tocleanstring(td) if text != '': account.label = text 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: account.type = account.TYPE_CARD account.coming = account.balance account.balance = Decimal('0') yield account
def get_list(self): l = [] for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"): account = Account() # account.id account.id = cpt.xpath("./span[1]/text()")[0].replace( u"\xa0", "").replace(',', '.').replace("EUR", "").replace( "\n", "").replace("\t", "").replace(u"\xb0", '').replace(" ", "").replace('N', '') # account balance account.balance = Decimal( cpt.xpath("./span[2]/text()")[0].replace("+", "").replace( u"\xa0", "").replace(',', '.').replace("EUR", "").replace( "\n", "").replace("\t", "").replace(" ", "")) # account coming TODO #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0] #mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") #if mycomingval == '-': # account.coming = Decimal(0) #else: # account.coming = Decimal(mycomingval) # account._link_id url_to_parse = cpt.xpath('@href')[0].replace("\n", "") # link compte_id_re = re.compile( r'/prive/mes-comptes/([^/]+/).*COMPTE_ACTIF=([^\&]+)\&?') account._link_id = '/fr/prive/mes-comptes/%sconsulter-situation/consulter-solde.jsp?COMPTE_ACTIF=%s' % \ (compte_id_re.search(url_to_parse).groups()[0], compte_id_re.search(url_to_parse).groups()[1]) # account.label temp_label = cpt.xpath('./text()')[1].replace( u'-\xa0', '').replace("\n", "").replace("\t", "") account.label = " ".join(temp_label.split(" ")[:2]) l.append(account) return l
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 add_por_accounts(self, accounts): for ele in self.doc.xpath('//select[contains(@name, "POR_Synthese")]/option'): for a in accounts: if a.id.startswith(ele.attrib['value']): a._is_inv = True a.type = Account.TYPE_MARKET self.fill(a) break else: acc = Account() acc.id = ele.attrib['value'] if acc.id == '9999': # fake account continue acc.label = unicode(re.sub("\d", '', ele.text).strip()) acc._link_id = None acc.type = Account.TYPE_MARKET acc._is_inv = True self.fill(acc) accounts.append(acc)
def add_por_accounts(self, accounts): for ele in self.doc.xpath( '//select[contains(@name, "POR_Synthese")]/option'): for a in accounts: if a.id.startswith(ele.attrib['value']): a._is_inv = True a.type = Account.TYPE_MARKET self.fill(a) break else: acc = Account() acc.id = ele.attrib['value'] if acc.id == '9999': # fake account continue acc.label = unicode(re.sub("\d", '', ele.text).strip()) acc._link_id = None acc.type = Account.TYPE_MARKET acc._is_inv = True self.fill(acc) accounts.append(acc)
def get_list(self): l = [] for div in self.document.getiterator('div'): if div.attrib.get('id', '') == 'synthese-list': for tr in div.getiterator('tr'): account = Account() account.id = None for td in tr.getiterator('td'): if td.attrib.get('class', '') == 'account-cb': break elif td.attrib.get('class', '') == 'account-name': a = td.find('a') account.label = to_unicode(a.text) account._link_id = a.get('href', '') elif td.attrib.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.attrib.get('class', '') == 'account-total': span = td.find('span') if span == None: balance = td.text else: balance = span.text balance = balance.strip(u' \n\t€+').replace( ',', '.').replace(' ', '') if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None: l.append(account) return l
def get_list(self): l = [] for div in self.document.getiterator('div'): if div.attrib.get('id', '') == 'synthese-list': for tr in div.getiterator('tr'): account = Account() account.id = None for td in tr.getiterator('td'): if td.attrib.get('class', '') == 'account-cb': break elif td.attrib.get('class', '') == 'account-name': a = td.find('a') account.label = to_unicode(a.text) account._link_id = a.get('href', '') elif td.attrib.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.attrib.get('class', '') == 'account-total': span = td.find('span') if span == None: balance = td.text else: balance = span.text balance = balance.strip(u' \n\t€+').replace(',', '.').replace(' ', '') if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None: l.append(account) return l
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 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_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 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): blocks = self.document.xpath( '//div[@id="synthese-list"]//div[@class="block"]') for div in blocks: block_title = ''.join( div.xpath('.//span[@class="title"]//text()')).lower() for tr in div.getiterator('tr'): account = Account() account.id = None account._link_id = None if 'assurance vie' in block_title: # Life insurance accounts are investments account.type = Account.TYPE_MARKET for td in tr.getiterator('td'): if td.get('class', '') == 'account-cb': try: a = td.xpath('./*/a[@class="gras"]')[0] except IndexError: # ignore account break account.type = Account.TYPE_CARD account.label, account.id = [ s.strip() for s in self.parser.tocleanstring(td).rsplit( '-', 1) ] try: account._link_id = td.xpath('.//a')[0].get('href') except KeyError: pass elif td.get('class', '') == 'account-name': try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) account.id = self.parser.tocleanstring(td).rsplit( '-', 1)[-1].strip() try: account._link_id = td.xpath('.//a')[0].get('href') account._detail_url = account._link_id except KeyError: pass elif td.get('class', '') == 'account-more-actions': for a in td.getiterator('a'): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if 'href' in a.attrib and "mouvements.phtml" in a.get( 'href') and "/cartes/" not in a.get( 'href'): account._link_id = a.get('href') elif td.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.get('class', '') == 'account-total': span = td.find('span') balance = td.text if span is None else span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) account.balance = Decimal( balance) if balance != "" else Decimal(0) else: # because of some weird useless <tr> if account.id is not None and (not account._link_id or 'moneycenter' not in account._link_id): yield account
def get_list(self): err = CleanText('//span[@class="error_msg"]', default='')(self.doc) if err == 'Vous ne disposez pas de compte consultable.': raise NoAccountsException() def check_valid_url(url): pattern = ['/restitution/cns_detailAVPAT.html', '/restitution/cns_detailAlterna.html', ] for p in pattern: if url.startswith(p): return False return True accounts_list = [] for tr in self.doc.getiterator('tr'): if 'LGNTableRow' not 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 = CleanText('.')(a) account._link_id = a.get('href', '') for pattern, actype in self.TYPES.items(): if account.label.startswith(pattern): account.type = actype break else: if account._link_id.startswith('/asv/asvcns10.html'): account.type = Account.TYPE_LIFE_INSURANCE # Website crashes when going on theses URLs if not check_valid_url(account._link_id): account._link_id = None elif td.attrib.get('headers', '') == 'NumeroCompte': account.id = CleanText(u'.', replace=[(' ', '')])(td) elif td.attrib.get('headers', '') == 'Libelle': text = CleanText('.')(td) if text != '': account.label = text elif td.attrib.get('headers', '') == 'Solde': div = td.xpath('./div[@class="Solde"]') if len(div) > 0: balance = CleanText('.')(div[0]) if len(balance) > 0 and balance not in ('ANNULEE', 'OPPOSITION'): try: account.balance = Decimal(FrenchTransaction.clean_amount(balance)) except InvalidOperation: self.logger.error('Unable to parse balance %r' % balance) continue account.currency = account.get_currency(balance) else: account.balance = NotAvailable if not account.label or empty(account.balance): continue if account._link_id and 'CARTE_' in account._link_id: account.type = account.TYPE_CARD page = self.browser.open(account._link_id).page # Layout with several cards line = CleanText('//table//div[contains(text(), "Liste des cartes")]', replace=[(' ', '')])(page.doc) if line: parent_id = re.search(r'(\d+)', line).group() # Layout with only one card else: parent_id = CleanText('//div[contains(text(), "Numéro de compte débité")]/following::div[1]', replace=[(' ', '')])(page.doc) account.parent = find_object(accounts_list, id=parent_id) if account.type == Account.TYPE_UNKNOWN: self.logger.debug('Unknown account type: %s', account.label) accounts_list.append(account) return accounts_list
def get_list(self): blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]') for div in blocks: block_title = "".join(div.xpath('.//span[@class="title"]//text()')).lower() for tr in div.getiterator("tr"): account = Account() account.id = None account._link_id = None if "assurance vie" in block_title: # Life insurance accounts are investments account.type = Account.TYPE_MARKET for td in tr.getiterator("td"): if td.get("class", "") == "account-cb": try: a = td.xpath('./*/a[@class="gras"]')[0] except IndexError: # ignore account break account.type = Account.TYPE_CARD account.label, account.id = [s.strip() for s in self.parser.tocleanstring(td).rsplit("-", 1)] try: account._link_id = td.xpath(".//a")[0].get("href") except KeyError: pass elif td.get("class", "") == "account-name": try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) account.id = self.parser.tocleanstring(td).rsplit("-", 1)[-1].strip() try: account._link_id = td.xpath(".//a")[0].get("href") account._detail_url = account._link_id except KeyError: pass elif td.get("class", "") == "account-more-actions": for a in td.getiterator("a"): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if "mouvements.phtml" in a.get("href") and "/cartes/" not in a.get("href"): account._link_id = a.get("href") elif td.get("class", "") == "account-number": id = td.text id = id.strip(u" \n\t") account.id = id elif td.get("class", "") == "account-total": span = td.find("span") if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None: yield account
def get_list(self): blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]') for div in blocks: block_title = ''.join(div.xpath('.//span[@class="title"]/a/text()')).lower().strip() for tr in div.getiterator('tr'): account = Account() account.id = None account._link_id = None account.type = self.ACCOUNT_TYPES.get(block_title, Account.TYPE_UNKNOWN) if 'assurance vie' in block_title: # Life insurance accounts are investments account.type = Account.TYPE_LIFE_INSURANCE for td in tr.getiterator('td'): if td.get('class', '') == 'account-cb': try: a = td.xpath('./*/a[@class="gras"]')[0] except IndexError: # ignore account break account.type = Account.TYPE_CARD account.label, account.id = [s.strip() for s in self.parser.tocleanstring(td).rsplit('-', 1)] # Sometimes there is text after the card number: # <a class="gras" href="/comptes/banque/cartes/index.phtml?CompteCourant=ulietuliedtlueditluedt&currentCB=ruisecruicertuci"> # CARTE PREMIER </a> # <br>MACHIN BIDULE TRUC - 1111********1111 # # <br> # <strong><a href="/aide/faq/index.phtml?document_id=472">Son échéance est le <span style="color:#ff8400; font-weight:bold;">31/03/2015</span>.<br>En savoir plus</a></strong> # So we have to remove all the shit after it. account.id = account.id.split(' ')[0] try: account._link_id = td.xpath('.//a')[0].get('href') # Try to use account._link_id for account.id to prevent duplicate accounts currentCB = re.search('currentCB=(.*)', account._link_id) if currentCB: account.id = currentCB.group(1) except KeyError: pass elif td.get('class', '') == 'account-name': try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) account.id = self.parser.tocleanstring(td).rsplit('-', 1)[-1].strip() try: account._link_id = td.xpath('.//a')[0].get('href') account._detail_url = account._link_id except KeyError: pass elif td.get('class', '') == 'account-more-actions': for a in td.getiterator('a'): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if 'href' in a.attrib and "mouvements.phtml" in a.get('href') and "/cartes/" not in a.get('href'): account._link_id = a.get('href') elif td.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.get('class', '') == 'account-total': span = td.find('span') if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None and (not account._link_id or 'moneycenter' not in account._link_id): yield account
def get_list(self): err = CleanText('//span[@class="error_msg"]', default='')(self.doc) if err == 'Vous ne disposez pas de compte consultable.': raise NoAccountsException() def check_valid_url(url): pattern = [ '/restitution/cns_detailAVPAT.html', '/restitution/cns_detailAlterna.html', ] for p in pattern: if url.startswith(p): return False return True for tr in self.doc.getiterator('tr'): if 'LGNTableRow' not 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 = CleanText('.')(a) account._link_id = a.get('href', '') for pattern, actype in self.TYPES.items(): if account.label.startswith(pattern): account.type = actype break else: if account._link_id.startswith('/asv/asvcns10.html'): account.type = Account.TYPE_LIFE_INSURANCE # Website crashes when going on theses URLs if not check_valid_url(account._link_id): account._link_id = None elif td.attrib.get('headers', '') == 'NumeroCompte': account.id = CleanText(u'.', replace=[(' ', '')])(td) elif td.attrib.get('headers', '') == 'Libelle': text = CleanText('.')(td) if text != '': account.label = text elif td.attrib.get('headers', '') == 'Solde': div = td.xpath('./div[@class="Solde"]') if len(div) > 0: balance = CleanText('.')(div[0]) if len(balance) > 0 and balance not in ('ANNULEE', 'OPPOSITION'): try: account.balance = Decimal( FrenchTransaction.clean_amount(balance)) except InvalidOperation: self.logger.error( 'Unable to parse balance %r' % balance) continue account.currency = account.get_currency(balance) else: account.balance = NotAvailable if not account.label or empty(account.balance): continue if account._link_id and 'CARTE_' in account._link_id: account.type = account.TYPE_CARD if account.type == Account.TYPE_UNKNOWN: self.logger.debug('Unknown account type: %s', account.label) yield account
def get_list(self): blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]') for div in blocks: block_title = ''.join(div.xpath('.//span[@class="title"]//text()')).lower() for tr in div.getiterator('tr'): account = Account() account.id = None account._link_id = None if 'assurance vie' in block_title: # Life insurance accounts are investments account.type = Account.TYPE_MARKET for td in tr.getiterator('td'): if td.get('class', '') == 'account-cb': try: a = td.xpath('./*/a[@class="gras"]')[0] except IndexError: # ignore account break account.type = Account.TYPE_CARD account.label = self.parser.tocleanstring(a) try: account._link_id = td.xpath('.//a')[0].get('href') except KeyError: pass elif td.get('class', '') == 'account-name': try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) try: account._link_id = td.xpath('.//a')[0].get('href') account._detail_url = account._link_id except KeyError: pass elif td.get('class', '') == 'account-more-actions': for a in td.getiterator('a'): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if "mouvements.phtml" in a.get('href') and "/cartes/" not in a.get('href'): account._link_id = a.get('href') elif td.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.get('class', '') == 'account-total': span = td.find('span') if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None: yield account
def get_list(self): blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]') for div in blocks: block_title = "".join(div.xpath('.//span[@class="title"]/a/text()')).lower().strip() for tr in div.getiterator("tr"): account = Account() account.id = None account._link_id = None account.type = self.ACCOUNT_TYPES.get(block_title, Account.TYPE_UNKNOWN) if "assurance vie" in block_title: # Life insurance accounts are investments account.type = Account.TYPE_LIFE_INSURANCE for td in tr.getiterator("td"): if td.get("class", "") == "account-cb": try: a = td.xpath('./*/a[@class="gras"]')[0] except IndexError: # ignore account break account.type = Account.TYPE_CARD account.label, account.id = [s.strip() for s in self.parser.tocleanstring(td).rsplit("-", 1)] # Sometimes there is text after the card number: # <a class="gras" href="/comptes/banque/cartes/index.phtml?CompteCourant=ulietuliedtlueditluedt&currentCB=ruisecruicertuci"> # CARTE PREMIER </a> # <br>MACHIN BIDULE TRUC - 1111********1111 # # <br> # <strong><a href="/aide/faq/index.phtml?document_id=472">Son échéance est le <span style="color:#ff8400; font-weight:bold;">31/03/2015</span>.<br>En savoir plus</a></strong> # So we have to remove all the shit after it. account.id = account.id.split(" ")[0] try: account._link_id = td.xpath(".//a")[0].get("href") # Try to use account._link_id for account.id to prevent duplicate accounts currentCB = re.search("currentCB=(.*)", account._link_id) if currentCB: account.id = currentCB.group(1) except KeyError: pass elif td.get("class", "") == "account-name": try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) account.id = self.parser.tocleanstring(td).rsplit("-", 1)[-1].strip() try: account._link_id = td.xpath(".//a")[0].get("href") account._detail_url = account._link_id except KeyError: pass elif td.get("class", "") == "account-more-actions": for a in td.getiterator("a"): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if ( "href" in a.attrib and "mouvements.phtml" in a.get("href") and "/cartes/" not in a.get("href") ): account._link_id = a.get("href") elif td.get("class", "") == "account-number": id = td.text id = id.strip(u" \n\t") account.id = id elif td.get("class", "") == "account-total": span = td.find("span") if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None and (not account._link_id or "moneycenter" not in account._link_id): yield account
def get_list(self, pro=True): accounts = [] for tr in self.document.xpath('//tr[@class="comptes"]'): cols = tr.findall('td') if len(cols) < 5: continue account = Account() account.id = self.parser.tocleanstring(cols[self.COL_ID]).replace( " ", "") account.label = self.parser.tocleanstring(cols[self.COL_LABEL]) account.balance = Decimal( self.parser.tocleanstring(cols[self.COL_BALANCE])) try: account.coming = Decimal( self.parser.tocleanstring(cols[self.COL_COMING])) except InvalidOperation: if self.parser.tocleanstring(cols[self.COL_COMING]) != '-': self.logger.warning('Unable to parse coming value', exc_info=True) account.coming = NotAvailable account._link_id = None account._stp = None a = cols[self.COL_LABEL].find('a') if a is not None: url = urlparse(a.attrib['href']) p = dict(parse_qsl(url.query)) account._link_id = p.get('ch4', None) account._stp = p.get('stp', None) for input_tag in tr.xpath('.//input[starts-with(@id, "urlRib")]'): m = re.search('ch4=(\w+)', input_tag.get('value', '')) if m: account.iban = unicode(m.group(1)) break else: select = tr.xpath('.//select//@onchange')[0] m = re.search("\(this,'(\w+)", select) if m: iban = unicode(m.group(1)) if iban.startswith('FR') and len(iban) == 27: account.iban = unicode(m.group(1)) accounts.append(account) # If there are also personnal accounts linked, display the page and iter on them. if pro and len( self.document.xpath( '//div[@class="onglets"]//a[contains(@href, "afficherComptesPrives")]' )) > 0: self.browser.select_form(name='myForm') self.browser.set_all_readonly(False) self.browser['udcAction'] = '/afficherComptesPrives' self.browser.submit() for a in self.browser.page.get_list(False): accounts.append(a) return accounts
def get_list(self): blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]') for div in blocks: block_title = ''.join(div.xpath('.//span[@class="title"]//text()')).lower() for tr in div.getiterator('tr'): account = Account() account.id = None account._link_id = None if 'assurance vie' in block_title: # Life insurance accounts are investments account.type = Account.TYPE_LIFE_INSURANCE for td in tr.getiterator('td'): if td.get('class', '') == 'account-cb': try: a = td.xpath('./*/a[@class="gras"]')[0] except IndexError: # ignore account break account.type = Account.TYPE_CARD account.label, account.id = [s.strip() for s in self.parser.tocleanstring(td).rsplit('-', 1)] # Sometimes there is text after the card number: # <a class="gras" href="/comptes/banque/cartes/index.phtml?CompteCourant=ulietuliedtlueditluedt&currentCB=ruisecruicertuci"> # CARTE PREMIER </a> # <br>MACHIN BIDULE TRUC - 1111********1111 # # <br> # <strong><a href="/aide/faq/index.phtml?document_id=472">Son échéance est le <span style="color:#ff8400; font-weight:bold;">31/03/2015</span>.<br>En savoir plus</a></strong> # So we have to remove all the shit after it. account.id = account.id.split(' ')[0] try: account._link_id = td.xpath('.//a')[0].get('href') except KeyError: pass elif td.get('class', '') == 'account-name': try: span = td.xpath('./span[@class="label"]')[0] except IndexError: # ignore account break account.label = self.parser.tocleanstring(span) account.id = self.parser.tocleanstring(td).rsplit('-', 1)[-1].strip() try: account._link_id = td.xpath('.//a')[0].get('href') account._detail_url = account._link_id except KeyError: pass elif td.get('class', '') == 'account-more-actions': for a in td.getiterator('a'): # For normal account, two "account-more-actions" # One for the account, one for the credit card. Take the good one if 'href' in a.attrib and "mouvements.phtml" in a.get('href') and "/cartes/" not in a.get('href'): account._link_id = a.get('href') elif td.get('class', '') == 'account-number': id = td.text id = id.strip(u' \n\t') account.id = id elif td.get('class', '') == 'account-total': span = td.find('span') if span is None: balance = td.text else: balance = span.text account.currency = account.get_currency(balance) balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: account.balance = Decimal(0) else: # because of some weird useless <tr> if account.id is not None and (not account._link_id or not 'moneycenter' in account._link_id): yield account
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()