def iter_accounts(self): params = {} for field in self.document.xpath("//input"): params[field.attrib["name"]] = field.attrib.get("value", "") account = None for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'): cols = tr.xpath("./td") id = self.parser.tocleanstring(cols[self.COL_ID]) if len(id) > 0: if account is not None: yield account account = Account() account.id = id account.balance = account.coming = Decimal("0") account._next_debit = datetime.date.today() account._prev_debit = datetime.date(2000, 1, 1) account.label = u" ".join( [self.parser.tocleanstring(cols[self.COL_TYPE]), self.parser.tocleanstring(cols[self.COL_LABEL])] ) account._coming_params = params.copy() account._coming_params["dialogActionPerformed"] = "SELECTION_ENCOURS_CARTE" account._coming_params["attribute($SEL_$%s)" % tr.attrib["id"].split("_")[0]] = tr.attrib["id"].split( "_", 1 )[1] elif account is None: raise BrokenPageError("Unable to find accounts on cards page") else: account._params = params.copy() account._params["dialogActionPerformed"] = "SELECTION_ENCOURS_CARTE" account._params["attribute($SEL_$%s)" % tr.attrib["id"].split("_")[0]] = tr.attrib["id"].split("_", 1)[ 1 ] date_col = self.parser.tocleanstring(cols[self.COL_DATE]) m = re.search("(\d+)/(\d+)/(\d+)", date_col) if not m: self.logger.warning("Unable to parse date %r" % date_col) continue date = datetime.date(*reversed(map(int, m.groups()))) if date.year < 100: date = date.replace(year=date.year + 2000) amount = Decimal(FrenchTransaction.clean_amount(self.parser.tocleanstring(cols[self.COL_AMOUNT]))) if not date_col.endswith("(1)"): # debited account.coming += -abs(amount) account._next_debit = date elif date > account._prev_debit: account._prev_balance = -abs(amount) account._prev_debit = date if account is not None: yield account
def iter_accounts(self, next_pages): account_type = Account.TYPE_UNKNOWN params = {} for field in self.document.xpath('//input'): params[field.attrib['name']] = field.attrib.get('value', '') for div in self.document.getroot().cssselect('div.btit'): if div.text is None: continue account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN) if account_type is None: # ignore services accounts continue currency = None for th in div.getnext().xpath('.//thead//th'): m = re.match('.*\((\w+)\)$', th.text) if m and currency is None: currency = Account.get_currency(m.group(1)) for tr in div.getnext().xpath('.//tbody/tr'): if 'id' not in tr.attrib: continue args = dict(parse_qsl(tr.attrib['id'])) tds = tr.findall('td') if len(tds) < 4 or 'identifiant' not in args: self.logger.warning('Unable to parse an account') continue account = Account() account.id = args['identifiant'].replace(' ', '') account.label = u' '.join([u''.join([txt.strip() for txt in tds[1].itertext()]), u''.join([txt.strip() for txt in tds[2].itertext()])]).strip() account.type = account_type balance = FrenchTransaction.clean_amount(u''.join([txt.strip() for txt in tds[3].itertext()])) account.balance = Decimal(balance or '0.0') account.currency = currency if account.type == account.TYPE_LOAN: account.balance = - abs(account.balance) account._prev_debit = None account._next_debit = None account._params = None account._coming_params = None if balance != u'' and len(tds[3].xpath('.//a')) > 0: account._params = params.copy() account._params['dialogActionPerformed'] = 'SOLDE' account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] if len(tds) >= 5 and len(tds[self.COL_COMING].xpath('.//a')) > 0: _params = account._params.copy() _params['dialogActionPerformed'] = 'ENCOURS_COMPTE' next_pages.append(_params) yield account
def iter_accounts(self, next_pages): params = self.get_params() account = None currency = None for th in self.document.xpath('//table[@id="TabCtes"]//thead//th'): m = re.match('.*\((\w+)\)$', th.text) if m and currency is None: currency = Account.get_currency(m.group(1)) for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'): cols = tr.xpath('./td') id = self.parser.tocleanstring(cols[self.COL_ID]) if len(id) > 0: if account is not None: yield account account = Account() account.id = id.replace(' ', '') account.type = Account.TYPE_CARD account.balance = account.coming = Decimal('0') account._next_debit = datetime.date.today() account._prev_debit = datetime.date(2000, 1, 1) account.label = u' '.join([ self.parser.tocleanstring(cols[self.COL_TYPE]), self.parser.tocleanstring(cols[self.COL_LABEL]) ]) account.currency = currency account._params = None account._invest_params = None account._coming_params = params.copy() account._coming_params[ 'dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE' account._coming_params[ 'attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split( '_', 1)[1] elif account is None: raise BrokenPageError('Unable to find accounts on cards page') else: account._params = params.copy() account._params[ 'dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE' account._params[ 'attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split( '_', 1)[1] date_col = self.parser.tocleanstring(cols[self.COL_DATE]) m = re.search('(\d+)/(\d+)/(\d+)', date_col) if not m: self.logger.warning('Unable to parse date %r' % date_col) continue date = datetime.date(*reversed(map(int, m.groups()))) if date.year < 100: date = date.replace(year=date.year + 2000) amount = Decimal( FrenchTransaction.clean_amount( self.parser.tocleanstring(cols[self.COL_AMOUNT]))) if not date_col.endswith('(1)'): # debited account.coming += -abs(amount) account._next_debit = date elif date > account._prev_debit: account._prev_balance = -abs(amount) account._prev_debit = date if account is not None: yield account # Needed to preserve navigation. btn = self.document.xpath('.//button/span[text()="Retour"]') if len(btn) > 0: btn = btn[0].getparent() actions = self.get_button_actions() _params = params.copy() _params.update(actions[btn.attrib['id']]) self.browser.openurl('/cyber/internet/ContinueTask.do', urllib.urlencode(_params))
def iter_accounts(self, next_pages): account_type = Account.TYPE_UNKNOWN params = self.get_params() actions = self.get_button_actions() for div in self.document.getroot().cssselect('div.btit'): if div.text in (None, u'Synthèse'): continue account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN) if account_type is None: # ignore services accounts self.logger.debug('Ignore account type %s', div.text.strip()) continue # Go to the full list of this kind of account, if any. btn = div.getparent().xpath('.//button/span[text()="Suite"]') if len(btn) > 0: btn = btn[0].getparent() _params = params.copy() _params.update(actions[btn.attrib['id']]) next_pages.append(_params) continue currency = None for th in div.getnext().xpath('.//thead//th'): m = re.match('.*\((\w+)\)$', th.text) if m and currency is None: currency = Account.get_currency(m.group(1)) for tr in div.getnext().xpath('.//tbody/tr'): if 'id' not in tr.attrib: continue args = dict(parse_qsl(tr.attrib['id'])) tds = tr.findall('td') if len(tds) < 4 or 'identifiant' not in args: self.logger.warning('Unable to parse an account') continue account = Account() account.id = args['identifiant'].replace(' ', '') account.label = u' '.join([ u''.join([txt.strip() for txt in tds[1].itertext()]), u''.join([txt.strip() for txt in tds[2].itertext()]) ]).strip() account.type = account_type balance = FrenchTransaction.clean_amount(u''.join( [txt.strip() for txt in tds[3].itertext()])) account.balance = Decimal(balance or '0.0') account.currency = currency if account.type == account.TYPE_LOAN: account.balance = -abs(account.balance) account._prev_debit = None account._next_debit = None account._params = None account._coming_params = None account._invest_params = None if balance != u'' and len(tds[3].xpath('.//a')) > 0: account._params = params.copy() account._params['dialogActionPerformed'] = 'SOLDE' account._params[ 'attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split( '_', 1)[1] if len(tds) >= 5 and len( tds[self.COL_COMING].xpath('.//a')) > 0: _params = account._params.copy() _params['dialogActionPerformed'] = 'ENCOURS_COMPTE' # If there is an action needed before going to the cards page, save it. m = re.search('dialogActionPerformed=([\w_]+)', self.url) if m and m.group(1) != 'EQUIPEMENT_COMPLET': _params['prevAction'] = m.group(1) next_pages.append(_params) if not account._params: account._invest_params = params.copy() account._invest_params['dialogActionPerformed'] = 'CONTRAT' account._invest_params[ 'attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split( '_', 1)[1] yield account # Needed to preserve navigation. btn = self.document.xpath('.//button/span[text()="Retour"]') if len(btn) > 0: btn = btn[0].getparent() _params = params.copy() _params.update(actions[btn.attrib['id']]) self.browser.openurl('/cyber/internet/ContinueTask.do', urllib.urlencode(_params))
def iter_accounts(self, next_pages): params = self.get_params() account = None for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'): cols = tr.xpath('./td') id = self.parser.tocleanstring(cols[self.COL_ID]) if len(id) > 0: if account is not None: yield account account = Account() account.id = id.replace(' ', '') account.type = Account.TYPE_CARD account.balance = account.coming = Decimal('0') account._next_debit = datetime.date.today() account._prev_debit = datetime.date(2000,1,1) account.label = u' '.join([self.parser.tocleanstring(cols[self.COL_TYPE]), self.parser.tocleanstring(cols[self.COL_LABEL])]) account._params = None account._invest_params = None account._coming_params = params.copy() account._coming_params['dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE' account._coming_params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] elif account is None: raise BrokenPageError('Unable to find accounts on cards page') else: account._params = params.copy() account._params['dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE' account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] date_col = self.parser.tocleanstring(cols[self.COL_DATE]) m = re.search('(\d+)/(\d+)/(\d+)', date_col) if not m: self.logger.warning('Unable to parse date %r' % date_col) continue date = datetime.date(*reversed(map(int, m.groups()))) if date.year < 100: date = date.replace(year=date.year+2000) amount = Decimal(FrenchTransaction.clean_amount(self.parser.tocleanstring(cols[self.COL_AMOUNT]))) if not date_col.endswith('(1)'): # debited account.coming += - abs(amount) account._next_debit = date elif date > account._prev_debit: account._prev_balance = - abs(amount) account._prev_debit = date if account is not None: yield account # Needed to preserve navigation. btn = self.document.xpath('.//button/span[text()="Retour"]') if len(btn) > 0: btn = btn[0].getparent() actions = self.get_button_actions() _params = params.copy() _params.update(actions[btn.attrib['id']]) self.browser.openurl('/cyber/internet/ContinueTask.do', urllib.urlencode(_params))
def iter_accounts(self, next_pages): account_type = Account.TYPE_UNKNOWN params = self.get_params() actions = self.get_button_actions() for div in self.document.getroot().cssselect('div.btit'): if div.text in (None, u'Synthèse'): continue account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN) if account_type is None: # ignore services accounts continue # Go to the full list of this kind of account, if any. btn = div.getparent().xpath('.//button/span[text()="Suite"]') if len(btn) > 0: btn = btn[0].getparent() _params = params.copy() _params.update(actions[btn.attrib['id']]) next_pages.append(_params) continue currency = None for th in div.getnext().xpath('.//thead//th'): m = re.match('.*\((\w+)\)$', th.text) if m and currency is None: currency = Account.get_currency(m.group(1)) for tr in div.getnext().xpath('.//tbody/tr'): if 'id' not in tr.attrib: continue args = dict(parse_qsl(tr.attrib['id'])) tds = tr.findall('td') if len(tds) < 4 or 'identifiant' not in args: self.logger.warning('Unable to parse an account') continue account = Account() account.id = args['identifiant'].replace(' ', '') account.label = u' '.join([u''.join([txt.strip() for txt in tds[1].itertext()]), u''.join([txt.strip() for txt in tds[2].itertext()])]).strip() account.type = account_type balance = FrenchTransaction.clean_amount(u''.join([txt.strip() for txt in tds[3].itertext()])) account.balance = Decimal(balance or '0.0') account.currency = currency if account.type == account.TYPE_LOAN: account.balance = - abs(account.balance) account._prev_debit = None account._next_debit = None account._params = None account._coming_params = None account._invest_params = None if balance != u'' and len(tds[3].xpath('.//a')) > 0: account._params = params.copy() account._params['dialogActionPerformed'] = 'SOLDE' account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] if len(tds) >= 5 and len(tds[self.COL_COMING].xpath('.//a')) > 0: _params = account._params.copy() _params['dialogActionPerformed'] = 'ENCOURS_COMPTE' # If there is an action needed before going to the cards page, save it. m = re.search('dialogActionPerformed=([\w_]+)', self.url) if m and m.group(1) != 'EQUIPEMENT_COMPLET': _params['prevAction'] = m.group(1) next_pages.append(_params) if not account._params: account._invest_params = params.copy() account._invest_params['dialogActionPerformed'] = 'CONTRAT' account._invest_params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] yield account # Needed to preserve navigation. btn = self.document.xpath('.//button/span[text()="Retour"]') if len(btn) > 0: btn = btn[0].getparent() _params = params.copy() _params.update(actions[btn.attrib['id']]) self.browser.openurl('/cyber/internet/ContinueTask.do', urllib.urlencode(_params))
def iter_accounts(self, next_pages): account_type = Account.TYPE_UNKNOWN params = {} for field in self.document.xpath("//input"): params[field.attrib["name"]] = field.attrib.get("value", "") for div in self.document.getroot().cssselect("div.btit"): if div.text is None: continue account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN) if account_type is None: # ignore services accounts continue currency = None for th in div.getnext().xpath(".//thead//th"): m = re.match(".*\((\w+)\)$", th.text) if m and currency is None: currency = Account.get_currency(m.group(1)) for tr in div.getnext().xpath(".//tbody/tr"): if not "id" in tr.attrib: continue args = dict(parse_qsl(tr.attrib["id"])) tds = tr.findall("td") if len(tds) < 4 or not "identifiant" in args: self.logger.warning("Unable to parse an account") continue account = Account() account.id = args["identifiant"] account.label = u" ".join( [ u"".join([txt.strip() for txt in tds[1].itertext()]), u"".join([txt.strip() for txt in tds[2].itertext()]), ] ).strip() account.type = account_type balance = FrenchTransaction.clean_amount(u"".join([txt.strip() for txt in tds[3].itertext()])) account.balance = Decimal(balance or "0.0") account.currency = currency if account.type == account.TYPE_LOAN: account.balance = -abs(account.balance) account._prev_debit = None account._next_debit = None account._params = None account._coming_params = None if balance != u"" and len(tds[3].xpath(".//a")) > 0: account._params = params.copy() account._params["dialogActionPerformed"] = "SOLDE" account._params["attribute($SEL_$%s)" % tr.attrib["id"].split("_")[0]] = tr.attrib["id"].split( "_", 1 )[1] if len(tds) >= 5 and len(tds[self.COL_COMING].xpath(".//a")) > 0: _params = account._params.copy() _params["dialogActionPerformed"] = "ENCOURS_COMPTE" next_pages.append(_params) yield account
def iter_accounts(self, next_pages): params = self.get_params() account = None currency = None for th in self.doc.xpath('//table[@id="tbl1"]//thead//th'): m = re.match('.*\((\w+)\)$', th.text) if m and currency is None: currency = Account.get_currency(m.group(1)) if currency is None: currency = Account.get_currency(CleanText('//td[@id="tbl1_0_5_Cell"]//span')(self.doc)) for tr in self.doc.xpath('//table[@id="tbl1"]/tbody/tr'): cols = tr.xpath('./td') if len(cols) == 1 and CleanText('.')(cols[0]) == 'pas de carte': self.logger.debug('there are no cards on this page') continue id = CleanText(None).filter(cols[self.COL_ID]) if len(id) > 0: if account is not None: yield account account = Account() account.id = id.replace(' ', '') account.type = Account.TYPE_CARD account.balance = account.coming = Decimal('0') account._next_debit = datetime.date.today() account._prev_debit = datetime.date(2000,1,1) account.label = u' '.join([CleanText(None).filter(cols[self.COL_TYPE]), CleanText(None).filter(cols[self.COL_LABEL])]) account.currency = currency account._params = None account._invest_params = None account._coming_params = params.copy() account._coming_params['dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE' account._coming_params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] account._coming_count = len(self.doc.xpath('//table[@id="tbl1"]/tbody/tr/td[5]/span[not(contains(text(), "(1)"))]')) elif account is None: raise BrokenPageError('Unable to find accounts on cards page') else: account._params = params.copy() account._params['dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE' account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] date_col = CleanText(None).filter(cols[self.COL_DATE]) m = re.search('(\d+)/(\d+)/(\d+)', date_col) if not m: self.logger.warning('Unable to parse date %r' % date_col) continue date = datetime.date(*[int(c) for c in m.groups()][::-1]) if date.year < 100: date = date.replace(year=date.year+2000) amount = Decimal(FrenchTransaction.clean_amount(CleanText(None).filter(cols[self.COL_AMOUNT]))) if not date_col.endswith('(1)'): # debited account.coming += - abs(amount) account._next_debit = date elif date > account._prev_debit: account._prev_balance = - abs(amount) account._prev_debit = date if account is not None: yield account # Needed to preserve navigation. btn = self.doc.xpath('.//button[span[text()="Retour"]]') if len(btn) > 0: actions = self.get_button_actions() _params = params.copy() _params.update(actions[btn[0].attrib['id']]) self.browser.open('/cyber/internet/ContinueTask.do', data=_params)