def obj_id(self): href = CleanText('.//td[has-class("song-name")]//a/@href')( self) aid = href.split('/')[-2] sid = href.split('/')[-1].replace('paroles-', '') id = '%s|%s' % (aid, sid) return id
def obj_size(self): rawsize = CleanText('(//div[@id="infosficher"]/span)[1]')(self) rawsize = rawsize.replace(',','.').strip() nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper().replace('O','B') size = get_bytes_size(nsize,usize) return size
def obj_size(self): rawsize = CleanText( '//div[@class="accordion"]//tr[th="Taille totale"]/td')(self) nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper() size = get_bytes_size(nsize, usize) return size
def obj_size(self): rawsize = CleanText('./div[has-class("poid")]')(self) rawsize = rawsize.replace(',', '.').strip() nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper().replace('O', 'B') size = get_bytes_size(nsize, usize) return size
def obj_size(self): rawsize = CleanText('./div[has-class("poid")]')(self) rawsize = rawsize.replace(',','.').strip() nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper().replace('O','B') size = get_bytes_size(nsize,usize) return size
def obj_size(self): rawsize = CleanText('(//div[@id="infosficher"]/span)[1]')(self) rawsize = rawsize.replace(',', '.').strip() nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper().replace('O', 'B') size = get_bytes_size(nsize, usize) return size
def obj_size(self): rawsize = CleanText('./td[2]')(self) rawsize = rawsize.replace(',', '.') nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper() size = get_bytes_size(nsize, usize) return size
def obj_size(self): rawsize = CleanText('./td[2]')(self) rawsize = rawsize.replace(',','.') nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper() size = get_bytes_size(nsize,usize) return size
def obj_label(self): raw_label = CleanText(TableCell('label'))(self) label = CleanText(TableCell('label')(self)[0].xpath('./br/following-sibling::text()'))(self) if (label and label.split()[0] != raw_label.split()[0]) or not label: label = raw_label return CleanText(TableCell('label')(self)[0].xpath('./noscript'))(self) or label
def obj_label(self): raw_label = CleanText(TableCell('label'))(self) label = CleanText(TableCell('label')(self)[0].xpath('./br/following-sibling::text()'))(self) if (label and label.split()[0] != raw_label.split()[0]) or not label: label = raw_label return CleanText(TableCell('label')(self)[0].xpath('./noscript'))(self) or label
def obj_size(self): rawsize = CleanText('//span[has-class("folder") or has-class("folderopen")]')(self) rawsize = rawsize.split(': ')[-1].split(')')[0].strip() rawsize = rawsize.replace(',','.') nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper() size = get_bytes_size(nsize,usize) return size
def obj_size(self): rawsize = CleanText( '//span[has-class("folder") or has-class("folderopen")]')(self) rawsize = rawsize.split(': ')[-1].split(')')[0].strip() rawsize = rawsize.replace(',', '.') nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper() size = get_bytes_size(nsize, usize) return size
def obj_size(self): rawsize = CleanText('//div[has-class("files")]/../h5')(self) s = rawsize.split(',')[-1].replace(')', '') nsize = float(re.sub(r'[A-Za-z]', '', s)) usize = re.sub(r'[.0-9 ]', '', s).upper() size = get_bytes_size(nsize, usize) return size
def obj_size(self): data = CleanText('./dd/span[3]')(self) if data: value, unit = data.split() return get_bytes_size(float(value), unit) else: return float("NaN")
def obj_details(self): details = {} details["creationDate"] = Date( Regexp( CleanText( '//p[@class="offer-description-notes"]|//p[has-class("darkergrey")]' ), u'.*Mis en ligne : (\d{2}/\d{2}/\d{4}).*' ), dayfirst=True )(self) honoraires = CleanText( ( '//div[has-class("offer-price")]/span[has-class("lbl-agencyfees")]' ), default=None )(self) if honoraires: details["Honoraires"] = ( "{} (TTC, en sus)".format( honoraires.split(":")[1].strip() ) ) for li in XPath('//ul[@itemprop="description"]/li')(self): label = CleanText('./span[has-class("criteria-label")]')(li) value = CleanText('./span[has-class("criteria-value")]')(li) details[label] = value return details
def obj_details(self): details = {} details["creationDate"] = Date( Regexp( CleanText( '//p[@class="offer-description-notes"]|//p[has-class("darkergrey")]' ), u'.*Mis en ligne : (\d{2}/\d{2}/\d{4}).*' ), dayfirst=True )(self) honoraires = CleanText( ( '//div[has-class("offer-price")]/span[has-class("lbl-agencyfees")]' ), default=None )(self) if honoraires: details["Honoraires"] = ( "{} (TTC, en sus)".format( honoraires.split(":")[1].strip() ) ) for li in XPath('//ul[@itemprop="description"]/li')(self): label = CleanText('./div[has-class("criteria-label")]')(li) value = CleanText('./div[has-class("criteria-value")]')(li) details[label] = value return details
def obj_id(self): try: _id = CleanText('.//td/a/@id')(self) if not _id: ac_details_page = self.page.browser.open( Link('.//td/a')(self)).page else: if '-' in _id: split = _id.split('-') ac_details_page = self.page.browser.open( '/outil/UWVI/AssuranceVie/accesDetail?ID_CONTRAT=%s&PRODUCTEUR=%s' % (split[0], split[1])).page else: ac_details_page = self.page.browser.open( '/outil/UWVI/AssuranceVie/accesDetail?ID_CONTRAT=%s' % (_id)).page return CleanText('(//tr[3])/td[2]')(ac_details_page.doc) except ServerError: self.logger.debug( "link didn't work, trying with the form instead") # the above server error can cause the form to fail, so we may have to go back on the accounts list before submitting self.page.browser.open(self.page.url) # redirection to lifeinsurances accounts and comeback on Lcl original website page = self.obj__form().submit().page account_id = page.get_account_id() page.come_back() return account_id
def obj_details(self): charges = CleanText('.//span[@class="price-fees"]', default=None)(self) if charges: return {"fees": charges.split(":")[1].strip()} else: return NotLoaded
def obj_size(self): rawsize = CleanText('//div[has-class("files")]/../h5')(self) s = rawsize.split(',')[-1].replace(')', '') nsize = float(re.sub(r'[A-Za-z]', '', s)) usize = re.sub(r'[.0-9 ]', '', s).upper() size = get_bytes_size(nsize, usize) return size
def obj_publication_date(self): content = CleanText('./div[2]')(self) split_date = content.split('|')[0].split('/') if len(split_date) == 3: return date( int(split_date[2]) + 2000, int(split_date[1]), int(split_date[0])) return ''
def get_author(self): try: author = CleanText('.')(self.get_element_author()) if author.startswith('Par '): return author.split('Par ', 1)[1] else: return author except AttributeError: return ''
def next_page(self): js_datas = CleanText('//div[@id="js-data"]/@data-rest-search-request')(self) total_page = self.page.browser.get_total_page(js_datas.split("?")[-1]) m = re.match(".*page=(\d?)(?:&.*)?", self.page.url) if m: current_page = int(m.group(1)) next_page = current_page + 1 if next_page <= total_page: return self.page.url.replace("page=%d" % current_page, "page=%d" % next_page)
def next_page(self): js_datas = CleanText('//div[@id="js-data"]/@data-rest-search-request')(self) total_page = self.page.browser.get_total_page(js_datas.split('?')[-1]) m = re.match(".*page=(\d?)(?:&.*)?", self.page.url) if m: current_page = int(m.group(1)) next_page = current_page + 1 if next_page <= total_page: return self.page.url.replace('page=%d' % current_page, 'page=%d' % next_page)
def obj_details(self): charges = CleanText('.//span[@class="price-fees"]', default=None)(self) if charges: return { "fees": charges.split(":")[1].strip() } else: return NotLoaded
def check_errors(self): # check if user can add new recipient errors_id = ('popinClientNonEligible', 'popinClientNonEligibleBis') for error_id in errors_id: if self.doc.xpath('//script[contains(text(), "showDivJQInfo(\'%s\')")]' % error_id): msg = CleanText('//div[@id="%s"]//p' % error_id)(self.doc) # get the first sentence of information message # beacause the message is too long and contains unnecessary recommendations raise AddRecipientBankError(message=msg.split('.')[0])
def temperatures(self): offset = int( CleanText('string(sum(./preceding-sibling::td/@colspan))')( self)) length = int(CleanText('@colspan')(self)) temps = CleanText( '../../../tbody/tr[@class="meteogram-temperatures"]/td[position() > %d ' 'and position() <= %d]/div' % (offset, offset + length))(self) return [float(_.strip(u'\xb0')) for _ in temps.split()]
def obj_details(self): details = {} honoraires = CleanText( (self.offer_details_wrapper + '/div/div/p[@class="offer-agency-fees"]'), default=None)(self) if honoraires: details["Honoraires"] = ("{} (TTC, en sus)".format( honoraires.split(":")[1].strip())) return details
def obj_details(self): details = {} energy_value = CleanText( '//div[has-class("offer-energy-greenhouseeffect-summary")]//div[has-class("energy-summary")]', default=None )(self) if energy_value and len(energy_value) > 1: energy_value = energy_value.replace("DPE", "").strip()[0] if energy_value not in ["A", "B", "C", "D", "E", "F", "G"]: energy_value = None if energy_value is None: energy_value = NotAvailable details["DPE"] = energy_value greenhouse_value = CleanText( '//div[has-class("offer-energy-greenhouseeffect-summary")]//div[has-class("greenhouse-summary")]', default=None )(self) if greenhouse_value and len(greenhouse_value) > 1: greenhouse_value = greenhouse_value.replace("GES", "").strip()[0] if greenhouse_value not in ["A", "B", "C", "D", "E", "F", "G"]: greenhouse_value = None if greenhouse_value is None: greenhouse_value = NotAvailable details["GES"] = greenhouse_value details["creationDate"] = Date( Regexp( CleanText( '//p[@class="offer-description-notes"]|//p[has-class("darkergrey")]' ), u'.*Mis en ligne : (\d{2}/\d{2}/\d{4}).*' ), dayfirst=True )(self) honoraires = CleanText( ( '//div[has-class("offer-price")]/span[has-class("lbl-agencyfees")]' ), default=None )(self) if honoraires: details["Honoraires"] = ( "{} (TTC, en sus)".format( honoraires.split(":")[1].strip() ) ) for li in XPath('//ul[@itemprop="description"]/li')(self): label = CleanText('./div[has-class("criteria-label")]')(li) value = CleanText('./div[has-class("criteria-value")]')(li) details[label] = value return details
def check_errors(self): # check if user can add new recipient errors_id = ('popinClientNonEligible', 'popinClientNonEligibleBis') for error_id in errors_id: if self.doc.xpath( '//script[contains(text(), "showDivJQInfo(\'%s\')")]' % error_id): msg = CleanText('//div[@id="%s"]//p' % error_id)(self.doc) # get the first sentence of information message # beacause the message is too long and contains unnecessary recommendations raise AddRecipientBankError(message=msg.split('.')[0])
def obj_details(self): details = {} a = CleanText('//div[@class="box box-noborder"]/p[@class="size_13 darkergrey bold"]')(self) if a: splitted_a = a.split(':') dpe = Regexp(CleanText('//div[@id="energy-pyramid"]/img/@src'), 'http://mmf.logic-immo.com/mmf/fr/static/dpe/dpe_(\w)_b.gif', default="")(self) if len(splitted_a) > 1: details[splitted_a[0]] = '%s (%s)' % (splitted_a[1], dpe) elif dpe: details[splitted_a[0]] = '%s' return details
def obj_id(self): try: _id = CleanText('.//td/a/@id')(self) if not _id: ac_details_page = self.page.browser.open(Link('.//td/a')(self)).page else: split = _id.split('-') ac_details_page = self.page.browser.open('/outil/UWVI/AssuranceVie/accesDetail?ID_CONTRAT=%s&PRODUCTEUR=%s' % (split[0], split[1])).page return CleanText('(//tr[3])/td[2]')(ac_details_page.doc) except ServerError: # redirection to lifeinsurances accounts and comeback on Lcl original website page = self.obj__form().submit().page account_id = page.get_account_id() page.come_back() return account_id
def obj_currency(self): _id = CleanText('.//td/a/@id')(self) if not _id: ac_details_page = self.page.browser.open( Link('.//td/a')(self)).page else: split = _id.split('-') ac_details_page = self.page.browser.open( '/outil/UWVI/AssuranceVie/accesDetail?ID_CONTRAT=%s&PRODUCTEUR=%s' % (split[0], split[1])).page return Currency.get_currency( re.sub( r'[\d\,\ ]', '', CleanText('(//tr[8])/td[2]', default=NotAvailable)( ac_details_page.doc))) or NotAvailable
def obj_details(self): details = {} a = CleanText( '//div[@class="box box-noborder"]/p[@class="size_13 darkergrey bold"]' )(self) if a: splitted_a = a.split(':') dpe = Regexp( CleanText('//div[@id="energy-pyramid"]/img/@src'), 'http://mmf.logic-immo.com/mmf/fr/static/dpe/dpe_(\w)_b.gif', default="")(self) if len(splitted_a) > 1: details[splitted_a[0]] = '%s (%s)' % (splitted_a[1], dpe) elif dpe: details[splitted_a[0]] = '%s' return details
def obj_details(self): details = {} honoraires = CleanText( ( self.offer_details_wrapper + '/div/div/p[@class="offer-agency-fees"]' ), default=None )(self) if honoraires: details["Honoraires"] = ( "{} (TTC, en sus)".format( honoraires.split(":")[1].strip() ) ) return details
def obj_code(self): # We try to get the code from <a> div. If we didn't find code in url, # we try to find it in the cell text tablecell = TableCell('label', colspan=True)(self)[0] # url find try code_match = Regexp( Link(tablecell.xpath('./following-sibling::td[position()=1]/div/a')), r'sico=([A-Z0-9]*)', default=None)(self) if is_isin_valid(code_match): return code_match # cell text find try text = CleanText(tablecell.xpath('./following-sibling::td[position()=1]/div')[0])(self) for code in text.split(' '): if is_isin_valid(code): return code return NotAvailable
def obj_code(self): # We try to get the code from <a> div. If we didn't find code in url, # we try to find it in the cell text tablecell = TableCell('label', colspan=True)(self)[0] # url find try url = tablecell.xpath('./following-sibling::td[position()=1]/div/a')[0].attrib['href'] code_match = re.search(r'sico=([A-Z0-9]*)', url) if code_match: if is_isin_valid(code_match.group(1)): return code_match.group(1) # cell text find try text = CleanText(tablecell.xpath('./following-sibling::td[position()=1]/div')[0])(self) for code in text.split(' '): if is_isin_valid(code): return code return NotAvailable
def get_revolving_attributes(self, account): loan = Loan() loan.available_amount = CleanDecimal('//div/span[contains(text(), "Montant disponible")]/following-sibling::*[1]', replace_dots=True)(self.doc) loan.used_amount = CleanDecimal('//div/span[contains(text(), "Montant Utilisé")]/following-sibling::*[1]', replace_dots=True)(self.doc) loan.total_amount = CleanDecimal('//div/span[contains(text(), "Réserve accordée")]/following-sibling::*[1]', replace_dots=True)(self.doc) loan.last_payment_amount = CleanDecimal('//div/span[contains(text(), "Echéance Précédente")]/following-sibling::*[1]', replace_dots=True)(self.doc) loan.last_payment_date = Date(Regexp(CleanText('//div/span[contains(text(), "Echéance Précédente")]/following-sibling::*[2]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc) owner_name = CleanText('//a[@class="lien-entete login"]/span')(self.doc) loan.name = ' '.join(owner_name.split()[1:]) loan.id = account.id loan.currency = account.currency loan.label = account.label loan.balance = account.balance loan.coming = account.coming loan.type = account.type loan._uncleaned_id = account._uncleaned_id loan._multiple_type = account._multiple_type return loan
def get_loan_attributes(self, account): loan = Loan() loan.total_amount = CleanDecimal('//div/span[contains(text(), "Capital initial")]/following-sibling::*[1]', replace_dots=True)(self.doc) owner_name = CleanText('//a[@class="lien-entete login"]/span')(self.doc) loan.name = ' '.join(owner_name.split()[1:]) loan.subscription_date = Date(Regexp(CleanText('//h4[span[contains(text(), "Date de départ du prêt")]]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc) loan.maturity_date = Date(Regexp(CleanText('//h4[span[contains(text(), "Date de fin du prêt")]]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc) loan.rate = Eval(lambda x: x / 100, CleanDecimal('//div/span[contains(text(), "Taux fixe")]/following-sibling::*[1]', replace_dots=True))(self.doc) loan.last_payment_amount = CleanDecimal('//div[@class="txt-detail " and not (@style)]//span[contains(text(), "Echéance du")]/following-sibling::span[1]')(self.doc) loan.last_payment_date = Date(Regexp(CleanText('//div[@class="txt-detail " and not (@style)]//span[contains(text(), "Echéance du")]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc) loan.id = account.id loan.currency = account.currency loan.label = account.label loan.balance = account.balance loan.coming = account.coming loan.type = account.type loan._uncleaned_id = account._uncleaned_id loan._multiple_type = account._multiple_type return loan
def obj_id(self): try: _id = CleanText('.//td/a/@id')(self) if not _id: ac_details_page = self.page.browser.open(Link('.//td/a')(self)).page else: if '-' in _id: split = _id.split('-') ac_details_page = self.page.browser.open('/outil/UWVI/AssuranceVie/accesDetail?ID_CONTRAT=%s&PRODUCTEUR=%s' % (split[0], split[1])).page else: ac_details_page = self.page.browser.open('/outil/UWVI/AssuranceVie/accesDetail?ID_CONTRAT=%s' % (_id)).page return CleanText('(//tr[3])/td[2]')(ac_details_page.doc) except ServerError: self.logger.debug("link didn't work, trying with the form instead") # the above server error can cause the form to fail, so we may have to go back on the accounts list before submitting self.page.browser.open(self.page.url) # redirection to lifeinsurances accounts and comeback on Lcl original website page = self.obj__form().submit().page account_id = page.get_account_id() page.come_back() return account_id
def obj_id(self): id = CleanText('./@href')(self) return id.split('/')[-1]
def obj_date(self): time = CleanText(u'//span[@id="refresh_time"]')(self) time = [int(t) for t in time.split(":")] now = datetime.datetime.now() now.replace(hour=time[0], minute=time[1]) return now
def obj_date(self): time = CleanText(u'//span[@id="refresh_time"]')(self) time = [int(t) for t in time.split(":")] now = datetime.datetime.now() now.replace(hour=time[0], minute=time[1]) return now
def obj_id(self): href = CleanText('./@href')(self) aid = href.split('/')[-2] sid = href.split('/')[-1].replace('paroles-','') id = '%s|%s'%(aid, sid) return id
def get_history(self, account): # checking if the card is still valid if self.doc.xpath('//div[@id="errorbox"]'): return # adding a time delta because amex have hard time to put the date in a good interval beginning_date = self.get_beginning_debit_date() - datetime.timedelta(days=360) end_date = self.get_end_debit_date() guesser = ChaoticDateGuesser(beginning_date, end_date) # Since the site doesn't provide the debit_date, # we just use the date of beginning of the previous period. # If this date + 1 month is greater than today's date, # then the transaction is coming end_of_period = None previous_date = CleanText('//td[@id="colStatementBalance"]/div[3]', default=None)(self.doc) if previous_date: end_of_period = (parse_french_date(' '.join(previous_date.split()[1:4])) + relativedelta(months=1)).date() else: previous_date = CleanText('//select[@id="viewPeriod"]/option[@selected]', default=None)(self.doc) if previous_date: end_of_period = parse_french_date(' '.join(previous_date.split()[:3])) + relativedelta(days=-1) + relativedelta(months=1) end_of_period = end_of_period.date() _id = str(int(account._idforold)) for tr in reversed(self.doc.xpath('//div[@id="txnsSection"]//tbody[@id="tableBody-txnsCard%s"]/tr[@class="tableStandardText"]' % _id)): cols = tr.findall('td') t = Transaction() day, month = CleanText().filter(cols[self.COL_DATE]).split(' ', 1) day = int(day) month = self.parse_month(month) date = guesser.guess_date(day, month) vdate = None try: detail = cols[self.COL_TEXT].xpath('./div[has-class("hiddenROC")]')[0] except IndexError: pass else: m = re.search(r' (\d{2} \D{3,4})', (' '.join([txt.strip() for txt in detail.itertext()])).strip()) if m: vday, vmonth = m.group(1).strip().split(' ') vday = int(vday) vmonth = self.parse_month(vmonth) vdate = guesser.guess_date(vday, vmonth) detail.drop_tree() raw = (' '.join([txt.strip() for txt in cols[self.COL_TEXT].itertext()])).strip() credit = CleanText().filter(cols[self.COL_CREDIT]) debit = CleanText().filter(cols[self.COL_DEBIT]) if end_of_period is not None and datetime.date.today() < end_of_period: t._is_coming = True else: t._is_coming = False t.date = t.rdate = date t.vdate = vdate t.raw = re.sub(r'[ ]+', ' ', raw) t.label = re.sub('(.*?)( \d+)? .*', r'\1', raw).strip() t.amount = parse_decimal(credit or debit) * (1 if credit else -1) if t.raw in self.browser.SUMMARY_CARD_LABEL: t.type = t.TYPE_CARD_SUMMARY elif t.amount > 0: t.type = t.TYPE_ORDER else: t.date = end_of_period t.type = t.TYPE_DEFERRED_CARD yield t
def obj__invest_account_id(self): invest_account_id = CleanText( Dict('holdingSummaryInformation/0/accountNumber'))(self) return invest_account_id.split(' ')[0]
def obj__invest_account_id(self): invest_account_id = CleanText(Dict('accountNumber'))(self) return invest_account_id.split(' ')[0]
def temperatures(self): offset = int(CleanText('string(sum(./preceding-sibling::td/@colspan))')(self)) length = int(CleanText('@colspan')(self)) temps = CleanText('../../../tbody/tr[@class="meteogram-temperatures"]/td[position() > %d ' 'and position() <= %d]/div' % (offset, offset+length))(self) return [float(_.strip(u'\xb0')) for _ in temps.split()]
def obj_id(self): acc_id = CleanText(Dict('accountNumber'))(self) return acc_id.split(' ')[0]
def obj_place(self): content = CleanText('./div[2]')(self) if len(content.split('|')) > 1: return content.split('|')[1] return ''
def obj_id(self): href = CleanText('./@href')(self) aid = href.split('/')[-2] sid = href.split('/')[-1].replace('paroles-', '') id = '%s|%s' % (aid, sid) return id
def obj__invest_account_id(self): invest_account_id = CleanText(Dict('accountNumber'))(self) return invest_account_id.split(' ')[0]
def obj_id(self): href = CleanText('.//td[has-class("song-name")]//a/@href')(self) aid = href.split('/')[-2] sid = href.split('/')[-1].replace('paroles-','') id = '%s|%s'%(aid, sid) return id
def obj_id(self): acc_id = CleanText(Dict('accountNumber'))(self) return acc_id.split(' ')[0]
def obj_size(self): rawsize = CleanText('//div[@class="accordion"]//tr[th="Taille totale"]/td')(self) nsize = float(rawsize.split()[0]) usize = rawsize.split()[-1].upper() size = get_bytes_size(nsize, usize) return size
def obj_publication_date(self): content = CleanText('./div[2]')(self) split_date = content.split('|')[0].split('/') if len(split_date) == 3: return date(int(split_date[2]) + 2000, int(split_date[1]), int(split_date[0])) return ''
def obj__invest_account_id(self): invest_account_id = CleanText(Dict( 'holdingSummaryInformation/0/accountNumber' ))(self) return invest_account_id.split(' ')[0]
def obj_url(self): href = CleanText('.//a[has-class("titre")]/@href')(self) subid = href.split('/')[-1].replace('.html','.torrent') return 'http://www.cpasbien.cm/telechargement/%s'%subid