[Ameli]&[Amelipro] Update after sites changes, and upgrade to new browser

This commit is contained in:
Kitof 2013-12-17 22:22:52 +01:00 committed by Romain Bignon
commit 10c5abc3d4
7 changed files with 251 additions and 229 deletions

91
modules/ameli/browser.py Normal file → Executable file
View file

@ -17,7 +17,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.deprecated.browser import Browser, BrowserIncorrectPassword
from weboob.browser import LoginBrowser, URL, need_login
from weboob.exceptions import BrowserIncorrectPassword
from weboob.capabilities.bill import Detail
from decimal import Decimal
from .pages import LoginPage, HomePage, AccountPage, LastPaymentsPage, PaymentDetailsPage, BillsPage
@ -25,80 +26,66 @@ from .pages import LoginPage, HomePage, AccountPage, LastPaymentsPage, PaymentDe
__all__ = ['AmeliBrowser']
class AmeliBrowser(Browser):
PROTOCOL = 'https'
DOMAIN = 'assure.ameli.fr'
ENCODING = None
class AmeliBrowser(LoginBrowser):
BASEURL = 'https://assure.ameli.fr'
PAGES = {'.*_pageLabel=as_login_page.*': LoginPage,
'.*_pageLabel=as_accueil_page.*': HomePage,
'.*_pageLabel=as_etat_civil_page.*': AccountPage,
'.*_pageLabel=as_revele_mensuel_presta_page.*': BillsPage,
'.*_pageLabel=as_dernier_paiement_page': LastPaymentsPage,
'.*_actionOverride=%2Fportlets%2Fpaiements%2Fdetailpaiements&paiements.*': PaymentDetailsPage
}
loginp = URL('/PortailAS/appmanager/PortailAS/assure\?.*_pageLabel=as_login_page', LoginPage)
homep = URL('/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_accueil_page', HomePage)
accountp = URL('/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_info_perso_page', AccountPage)
billsp = URL('/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_revele_mensuel_presta_page', BillsPage)
paymentdetailsp = URL('/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_dernier_paiement_page&paiements_1_actionOverride=%2Fportlets%2Fpaiements%2Fdetailpaiements&paiements_1idPaiement=.*', PaymentDetailsPage)
lastpaymentsp = URL('/PortailAS/appmanager/PortailAS/assure\?_nfpb=true&_pageLabel=as_dernier_paiement_page$', LastPaymentsPage)
loginp = '/PortailAS/appmanager/PortailAS/assure?_somtc=true&_pageLabel=as_login_page'
homep = '/PortailAS/appmanager/PortailAS/assure?_nfpb=true&_pageLabel=as_accueil_page'
accountp = '/PortailAS/appmanager/PortailAS/assure?_nfpb=true&_pageLabel=as_etat_civil_page'
billsp = '/PortailAS/appmanager/PortailAS/assure?_nfpb=true&_pageLabel=as_revele_mensuel_presta_page'
lastpaymentsp = '/PortailAS/appmanager/PortailAS/assure?_nfpb=true&_pageLabel=as_dernier_paiement_page'
logged = False
is_logging = False
def do_login(self):
self.logger.debug('call Browser.do_login')
if self.logged:
return True
def home(self):
self.logger.debug('call Browser.home')
self.location(self.homep)
if ((not self.is_logged()) and (not self.is_logging)):
self.login()
self.loginp.stay_or_go()
if self.homep.is_here():
self.logged = True
return True
def is_logged(self):
self.logger.debug('call Browser.is_logged')
return self.page.is_logged()
def login(self):
self.logger.debug('call Browser.login')
# Do we really need to login?
if self.is_logged():
self.logger.debug('Already logged in')
return
if self.is_logging:
return
self.is_logging = True
self.location(self.loginp)
self.page.login(self.username, self.password)
if not self.is_logged():
self.homep.stay_or_go() # Redirection not interpreted by browser. Mannually redirect on homep
if not self.homep.is_here():
raise BrowserIncorrectPassword()
self.is_logging = False
self.logged = True
@need_login
def iter_subscription_list(self):
if not self.is_on_page(AccountPage):
self.location(self.accountp)
self.logger.debug('call Browser.iter_subscription_list')
self.accountp.stay_or_go()
return self.page.iter_subscription_list()
@need_login
def get_subscription(self, id):
self.logger.debug('call Browser.get_subscription')
assert isinstance(id, basestring)
for sub in self.iter_subscription_list():
if id == sub._id:
return sub
return None
@need_login
def iter_history(self, sub):
if not self.is_on_page(LastPaymentsPage):
self.location(self.lastpaymentsp)
self.logger.debug('call Browser.iter_history')
self.lastpaymentsp.stay_or_go()
urls = self.page.iter_last_payments()
for url in urls:
self.location(url)
assert self.is_on_page(PaymentDetailsPage)
assert self.paymentdetailsp.is_here()
for payment in self.page.iter_payment_details(sub):
yield payment
@need_login
def iter_details(self, sub):
self.logger.debug('call Browser.iter_details')
det = Detail()
det.id = sub.id
det.label = sub.label
@ -106,17 +93,21 @@ class AmeliBrowser(Browser):
det.price = Decimal('0.0')
yield det
@need_login
def iter_bills(self, sub):
self.logger.debug('call Browser.iter_bills')
if not sub._id.isdigit():
return []
if not self.is_on_page(BillsPage):
self.location(self.billsp)
return self.page.iter_bills(sub)
self.billsp.stay_or_go()
return self.page.iter_bills(sub)
@need_login
def get_bill(self, id):
self.logger.debug('call Browser.get_bill')
assert isinstance(id, basestring)
subs = self.iter_subscription_list()
for sub in subs:
for b in self.iter_bills(sub):
if id == b.id:
return b
return False

24
modules/ameli/module.py Normal file → Executable file
View file

@ -17,7 +17,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
import urllib
from weboob.capabilities.bill import CapBill, SubscriptionNotFound, BillNotFound, Subscription, Bill
from weboob.tools.backend import Module, BackendConfig
from weboob.tools.value import ValueBackendPassword
@ -35,13 +34,12 @@ class AmeliModule(Module, CapBill):
LICENSE = 'AGPLv3+'
BROWSER = AmeliBrowser
CONFIG = BackendConfig(ValueBackendPassword('login',
label='numero de SS',
label='Numero de SS',
masked=False),
ValueBackendPassword('password',
label='Password',
masked=True)
)
BROWSER = AmeliBrowser
def create_default_browser(self):
return self.create_browser(self.config['login'].get(),
@ -51,8 +49,7 @@ class AmeliModule(Module, CapBill):
return self.browser.iter_subscription_list()
def get_subscription(self, _id):
with self.browser:
subscription = self.browser.get_subscription(_id)
subscription = self.browser.get_subscription(_id)
if not subscription:
raise SubscriptionNotFound()
else:
@ -61,24 +58,20 @@ class AmeliModule(Module, CapBill):
def iter_bills_history(self, subscription):
if not isinstance(subscription, Subscription):
subscription = self.get_subscription(subscription)
with self.browser:
return self.browser.iter_history(subscription)
return self.browser.iter_history(subscription)
def get_details(self, subscription):
if not isinstance(subscription, Subscription):
subscription = self.get_subscription(subscription)
with self.browser:
return self.browser.iter_details(subscription)
return self.browser.iter_details(subscription)
def iter_bills(self, subscription):
if not isinstance(subscription, Subscription):
subscription = self.get_subscription(subscription)
with self.browser:
return self.browser.iter_bills(subscription)
return self.browser.iter_bills(subscription)
def get_bill(self, id):
with self.browser:
bill = self.browser.get_bill(id)
bill = self.browser.get_bill(id)
if not bill:
raise BillNotFound()
else:
@ -87,5 +80,6 @@ class AmeliModule(Module, CapBill):
def download_bill(self, bill):
if not isinstance(bill, Bill):
bill = self.get_bill(bill)
with self.browser:
return self.browser.readurl(bill._url, urllib.urlencode(bill._args))
request = self.browser.open(bill._url, stream=True)
assert(request.headers['content-type'] == "application/pdf")
return request.content

View file

@ -22,53 +22,48 @@ from datetime import datetime
import re
import urllib
from decimal import Decimal
from weboob.deprecated.browser import Page, BrokenPageError
from weboob.browser.pages import HTMLPage
from weboob.capabilities.bill import Subscription, Detail, Bill
from weboob.browser.filters.standard import CleanText
# Ugly array to avoid the use of french locale
FRENCH_MONTHS = [u'janvier', u'février', u'mars', u'avril', u'mai', u'juin', u'juillet', u'août', u'septembre', u'octobre', u'novembre', u'décembre']
class AmeliBasePage(Page):
class AmeliBasePage(HTMLPage):
def is_logged(self):
try:
self.parser.select(self.document.getroot(), 'a.logout', 1)
except BrokenPageError:
logged = False
else:
if self.doc.xpath('//a[@id="id_lien_deco"]'):
logged = True
else:
logged = False
self.logger.debug('logged: %s' % (logged))
return logged
class LoginPage(AmeliBasePage):
def login(self, login, password):
self.browser.select_form('connexionCompteForm')
self.browser["connexioncompte_2numSecuriteSociale"] = login.encode('utf8')
self.browser["connexioncompte_2codeConfidentiel"] = password.encode('utf8')
self.browser.submit()
form = self.get_form('//form[@name="connexionCompteForm"]')
form['connexioncompte_2numSecuriteSociale'] = login.encode('utf8')
form['connexioncompte_2codeConfidentiel'] = password.encode('utf8')
form.submit()
class HomePage(AmeliBasePage):
pass
class AccountPage(AmeliBasePage):
def iter_subscription_list(self):
idents = self.document.xpath('//div[contains(@class, "blocfond")]')
enfants = 0
for ident in idents:
if len(ident.xpath('.//h3')) == 0:
continue
name = CleanText('//div[@id="bloc_contenu_masituation"]/h3', replace=[('Titulaire du compte : ', '')])(self.doc)
number = re.sub('[^\d]+', '', self.doc.xpath('//div[@id="bloc_contenu_masituation"]/ul/li')[2].text)
sub = Subscription(number)
sub._id = number
sub.label = unicode(name)
sub.subscriber = unicode(name)
yield sub
name = self.parser.tocleanstring(ident.xpath('.//h3')[0])
lis = ident.xpath('.//li')
if len(lis) > 3:
number = re.sub('[^\d]+', '', ident.xpath('.//li')[3].text)
else:
enfants = enfants + 1
number = "AFFILIE" + str(enfants)
nb_childs = 0
childs = self.doc.xpath('//div[@class="bloc_infos"]')
for child in childs:
name = CleanText('.//h3[1]')(child)
nb_childs = nb_childs + 1
number = "AFFILIE" + str(nb_childs)
sub = Subscription(number)
sub._id = number
sub.label = unicode(name)
@ -78,14 +73,14 @@ class AccountPage(AmeliBasePage):
class LastPaymentsPage(AmeliBasePage):
def iter_last_payments(self):
list_table = self.document.xpath('//table[@id="tabDerniersPaiements"]')
list_table = self.doc.xpath('//table[@id="tabDerniersPaiements"]')
if len(list_table) > 0:
table = list_table[0].xpath('.//tr')
for tr in table:
list_a = tr.xpath('.//a')
if len(list_a) == 0:
continue
yield list_a[0].attrib.get('href')
yield list_a[0].attrib.get('href').replace(':443','')
class PaymentDetailsPage(AmeliBasePage):
@ -94,39 +89,86 @@ class PaymentDetailsPage(AmeliBasePage):
idx = 0
else:
idx = sub._id.replace('AFFILIE', '')
if len(self.document.xpath('//div[@class="centrepage"]/h2')) > idx or self.document.xpath('//table[@id="DetailPaiement3"]') > idx:
id_str = self.document.xpath('//div[@class="centrepage"]/h2')[idx].text.strip()
if len(self.doc.xpath('//div[@class="centrepage"]/h2')) > idx or self.doc.xpath('//table[@id="DetailPaiement3"]') > idx:
id_str = self.doc.xpath('//div[@class="centrepage"]/h2')[idx].text.strip()
m = re.match('.*le (.*) pour un montant de.*', id_str)
if m:
id_str = m.group(1)
id_date = datetime.strptime(id_str, '%d/%m/%Y').date()
id = sub._id + "." + datetime.strftime(id_date, "%Y%m%d")
table = self.document.xpath('//table[@class="tableau"]')[idx].xpath('.//tr')
table = self.doc.xpath('//table[@class="tableau"]')[idx].xpath('.//tr')
line = 1
last_date = None
for tr in table:
tds = tr.xpath('.//td')
if len(tds) == 0:
continue
date_str = tds[0].text
det = Detail()
det.id = id + "." + str(line)
det.label = unicode(tds[1].text.strip())
if date_str is None or date_str == '':
det.infos = u''
det.datetime = last_date
else:
det.infos = u'Payé ' + unicode(re.sub('[^\d,-]+', '', tds[2].text)) + u'€ / Base ' + unicode(re.sub('[^\d,-]+', '', tds[3].text)) + u'€ / Taux ' + unicode(re.sub('[^\d,-]+', '', tds[4].text)) + '%'
det.datetime = datetime.strptime(date_str, '%d/%m/%Y').date()
last_date = det.datetime
det.price = Decimal(re.sub('[^\d,-]+', '', tds[5].text).replace(',', '.'))
if len(tds) == 5:
date_str = tds[0].text
det.id = id + "." + str(line)
det.label = unicode(tds[1].text.strip())
jours = tds[2].text
if jours is None:
jours = '0'
montant = tds[3].text
if montant is None:
montant = '0'
price = tds[4].text
if price is None:
price = '0'
if date_str is None or date_str == '':
det.infos = u''
det.datetime = last_date
else:
det.infos = date_str + u' (' + unicode(re.sub('[^\d,-]+', '', jours)) + u'j) * ' + unicode(re.sub('[^\d,-]+', '', montant)) + u''
det.datetime = datetime.strptime(date_str.split(' ')[3], '%d/%m/%Y').date()
last_date = det.datetime
det.price = Decimal(re.sub('[^\d,-]+', '', price).replace(',', '.'))
if len(tds) == 6:
date_str = tds[0].text
det.id = id + "." + str(line)
det.label = unicode(tds[1].text.strip())
paye = tds[2].text
if paye is None:
paye = '0'
base = tds[3].text
if base is None:
base = '0'
taux = tds[4].text
if taux is None:
taux = '0'
price = tds[5].text
if price is None:
price = '0'
if date_str is None or date_str == '':
det.infos = u''
det.datetime = last_date
else:
det.infos = u'Payé ' + unicode(re.sub('[^\d,-]+', '', paye)) + u'€ / Base ' + unicode(re.sub('[^\d,-]+', '', base)) + u'€ / Taux ' + unicode(re.sub('[^\d,-]+', '', taux)) + '%'
det.datetime = datetime.strptime(date_str, '%d/%m/%Y').date()
last_date = det.datetime
det.price = Decimal(re.sub('[^\d,-]+', '', price).replace(',', '.'))
line = line + 1
yield det
class BillsPage(AmeliBasePage):
def iter_bills(self, sub):
table = self.document.xpath('//table[@id="tableauDecompte"]')[0].xpath('.//tr')
table = self.doc.xpath('//table[@id="relevesMensuels"]')[0].xpath('.//tr')
for tr in table:
list_tds = tr.xpath('.//td')
if len(list_tds) == 0:
@ -137,15 +179,14 @@ class BillsPage(AmeliBasePage):
amount = list_tds[1].text
if amount is None:
continue
amount = re.sub(' euros', '', amount)
amount = re.sub('[^\d,-]+', '', amount)
bil = Bill()
bil.id = sub._id + "." + date.strftime("%Y%m")
bil.date = date
bil.label = u''+amount.strip()
bil.price = Decimal('-'+amount.strip().replace(',','.'))
bil.format = u'pdf'
filedate = date.strftime("%m%Y")
bil._url = '/PortailAS/PDFServletReleveMensuel.dopdf'
bil._args = {'PDF.moisRecherche': filedate}
bil.label = date.strftime("%Y%m%d")
bil._url = '/PortailAS/PDFServletReleveMensuel.dopdf?PDF.moisRecherche='+date.strftime("%m%Y")
yield bil
def get_bill(self, bill):