[transilien] fix #938 and adapt to brower2

This commit is contained in:
Bezleputh 2014-08-29 19:46:00 +02:00
commit f4576b5921
8 changed files with 218 additions and 607 deletions

View file

@ -17,14 +17,10 @@
# 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.capabilities.travel import CapTravel, Station, Departure, RoadStep
from weboob.capabilities.travel import CapTravel
from weboob.tools.backend import BaseBackend
from .browser import Transilien
from .stations import STATIONS
class TransilienBackend(BaseBackend, CapTravel):
@ -37,32 +33,10 @@ class TransilienBackend(BaseBackend, CapTravel):
BROWSER = Transilien
def iter_station_search(self, pattern):
pattern = pattern.lower()
for _id, name in STATIONS.iteritems():
if name.lower().find(pattern) >= 0:
yield Station(_id, name)
return self.browser.get_stations(pattern)
def iter_station_departures(self, station_id, arrival_id=None, date=None):
with self.browser:
for i, d in enumerate(self.browser.iter_station_departures(station_id, arrival_id)):
departure = Departure(i, d['type'], d['time'])
departure.departure_station = d['departure']
departure.arrival_station = d['arrival']
departure.late = d['late']
departure.information = d['late_reason']
departure.plateform = d['plateform']
yield departure
return self.browser.get_station_departues(station_id.replace('-', ' '), arrival_id, date)
def iter_roadmap(self, departure, arrival, filters):
with self.browser:
roadmap = self.browser.get_roadmap(departure, arrival, filters)
for s in roadmap['steps']:
step = RoadStep(s['id'])
step.line = s['line']
step.start_time = s['start_time']
step.end_time = s['end_time']
step.departure = s['departure']
step.arrival = s['arrival']
step.duration = s['duration']
yield step
return self.browser.get_roadmap(departure, arrival, filters)

View file

@ -16,56 +16,52 @@
#
# 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 datetime import datetime
from weboob.tools.browser2 import PagesBrowser, URL
from .pages import StationsPage, DeparturesPage, DeparturesPage2, HorairesPage, RoadMapPage
from weboob.tools.browser import BaseBrowser, BasePage, BrowserUnavailable
class Transilien(PagesBrowser):
from .pages.departures import DeparturesPage
from .pages.roadmap import RoadmapSearchPage, RoadmapConfirmPage, RoadmapPage
BASEURL = 'http://www.transilien.com'
stations_page = URL('aidesaisie/autocompletion\?saisie=(?P<pattern>.*)', StationsPage)
departures_page = URL('gare/pagegare/chargerGare\?nomGare=(?P<station>.*)',
'gare/.*', DeparturesPage)
departures_page2 = URL('fichehoraire/fichehoraire/(?P<url>.*)',
'fichehoraire/fichehoraire/.*', DeparturesPage2)
horaires_page = URL('fiche-horaire/(?P<station>.*)--(?P<arrival>.*)-(?P<station2>.*)-(?P<arrival2>)-(?P<date>)',
'fiche-horaire/.*', HorairesPage)
class UnavailablePage(BasePage):
def on_loaded(self):
raise BrowserUnavailable('Website is currently unavailable')
class Transilien(BaseBrowser):
DOMAIN = 'www.transilien.com'
PROTOCOL = 'https'
USER_AGENT = BaseBrowser.USER_AGENTS['microb']
PAGES = {'https://www\.transilien\.com/web/ITProchainsTrainsAvecDest\.do\?.*': DeparturesPage,
'https://www\.transilien\.com/web/ITProchainsTrains\.do\?.*': DeparturesPage,
'https://www\.transilien\.com/web/site.*': RoadmapSearchPage,
'https://www\.transilien\.com/web/RedirectHI.do.*': RoadmapConfirmPage,
'https://www\.transilien\.com/web/RedirectHIIntermediaire.do.*': RoadmapPage,
'https://www\.transilien\.com/transilien_sncf_maintenance_en_cours.htm': UnavailablePage,
}
def is_logged(self):
""" Do not need to be logged """
return True
def iter_station_search(self, pattern):
pass
def iter_station_departures(self, station_id, arrival_id=None):
if arrival_id:
self.location('https://www.transilien.com/web/ITProchainsTrainsAvecDest.do?codeTr3aDepart=%s&codeTr3aDest=%s&urlModule=/site/pid/184&gareAcc=true' % (station_id, arrival_id))
else:
self.location('https://www.transilien.com/web/ITProchainsTrains.do?tr3a=%s&urlModule=/site/pid/184' % station_id)
return self.page.iter_routes()
roadmap_page = URL('itineraire/rechercheitineraire/(?P<url>.*)',
'itineraire/rechercheitineraire/.*', RoadMapPage)
def get_roadmap(self, departure, arrival, filters):
self.location('/web/site/accueil/etat-trafic/chercher-itineraire/lang/en')
dep = self.get_stations(departure, False).next().name
arr = self.get_stations(arrival, False).next().name
self.roadmap_page.go(url='init').request_roadmap(dep, arr, filters.arrival_time)
return self.page.get_roadmap()
assert self.is_on_page(RoadmapSearchPage)
self.page.search(departure, arrival, filters.departure_time, filters.arrival_time)
def get_stations(self, pattern, only_station=True):
return self.stations_page.go(pattern=pattern).get_stations(only_station=only_station)
assert self.is_on_page(RoadmapConfirmPage)
self.page.confirm()
def get_station_departues(self, station, arrival_id, date):
if arrival_id is not None:
arrival_name = arrival_id.replace('-', ' ')
self.departures_page2.go(url='init').init_departure(station)
assert self.is_on_page(RoadmapPage)
roadmap = {}
roadmap['steps'] = list(self.page.get_steps())
return roadmap
arrival = self.page.get_potential_arrivals().get(arrival_name)
if arrival:
station_id = self.page.get_station_id()
if date is None:
date = datetime.now()
_date = datetime.strftime(date, "%d/%m/%Y-%H:%M")
self.horaires_page.go(station=station.replace(' ', '-'), arrival=arrival_id, station2=station_id, arrival2=arrival, date=_date)
return self.page.get_departures(station, arrival_name, date)
return []
else:
return self.departures_page.go(station=station).get_departures(station=station)

171
modules/transilien/pages.py Normal file
View file

@ -0,0 +1,171 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010-2011 Julien Hébert, Romain Bignon
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# 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 re
from weboob.tools.browser2.page import JsonPage, HTMLPage, method
from weboob.tools.browser2.elements import TableElement, ItemElement, ListElement
from weboob.capabilities.travel import Station, Departure, RoadStep
from weboob.tools.browser2.filters import Dict, CleanText, TableCell, Filter, DateTime, Env, Link, Regexp, Duration
from weboob.tools.date import LinearDateGuesser
__all__ = ['StationsPage', 'DeparturesPage', 'DeparturesPage2', 'HorairesPage', 'RoadMapPage']
class DictElement(ListElement):
def find_elements(self):
if self.item_xpath is not None:
for el in self.el.get(self.item_xpath):
yield el
else:
yield self.el
class RoadMapDuration(Duration):
regexp = re.compile(r'(?P<mn>\d+)')
kwargs = {'minutes': 'mn'}
class DepartureTypeFilter(Filter):
def filter(self, el):
result = []
for img in el[0].getiterator(tag='img'):
result.append(img.attrib['alt'])
return u' '.join(result)
class Child(Filter):
def filter(self, el):
return list(el[0].iterchildren())
class RoadMapPage(HTMLPage):
def request_roadmap(self, station, arrival, arrival_date):
form = self.get_form('//form[@id="cRechercheItineraire"]')
form['depart'] = station
form['arrivee'] = arrival
form.submit()
def get_roadmap(self):
for step in self.doc.xpath('//table[@class="trajet_etapes"]/tr[@class="etape"]'):
roadstep = RoadStep()
roadstep.line = '%s %s' % (DepartureTypeFilter(step.xpath('./td[@class="moyen"]'))(self),
CleanText('./td[@class="moyen"]')(step))
roadstep.start_time = DateTime(CleanText('./th/span[@class="depart"]'),
LinearDateGuesser())(step)
roadstep.end_time = DateTime(CleanText('./th/span[@class="depart"]/following-sibling::span'),
LinearDateGuesser())(step)
roadstep.departure = CleanText('./td[@class="arret"]/p/strong')(step)
roadstep.arrival = CleanText('./td[@class="arret"]/p/following-sibling::p/strong')(step)
roadstep.duration = RoadMapDuration(CleanText('./td[@class="time"]'))(step)
yield roadstep
class HorairesPage(HTMLPage):
def get_departures(self, station, arrival, date):
for table in self.doc.xpath('//table[@class="trajet_horaires trajet_etapes"]'):
lignes = table.xpath('./tr[@class="ligne"]/th')
arrives = table.xpath('./tr[@class="arrivee"]/td')
departs = table.xpath('./tr[@class="depart"]/td')
items = zip(lignes, arrives, departs)
for item in items:
departure = Departure()
departure.id = Regexp(Link('./div/a'), '.*?vehicleJourneyExternalCode=(.*?)&.*?')(item[1])
departure.departure_station = station
departure.arrival_station = arrival
hour, minute = CleanText('./div/a')(item[1]).split('h')
departure.time = date.replace(hour=int(hour), minute=int(minute))
hour, minute = CleanText('./div/a')(item[2]).split('h')
departure.arrival_time = date.replace(hour=int(hour), minute=int(minute))
departure.information = CleanText('.')(item[0])
departure.type = DepartureTypeFilter(item)(self)
yield departure
class StationsPage(JsonPage):
@method
class get_stations(DictElement):
item_xpath = 'gares'
class item(ItemElement):
klass = Station
def condition(self):
if self.env['only_station']:
return Dict('entryPointType')(self.el) == 'StopArea' and Dict('reseau')(self.el)[0]
return True
obj_name = CleanText(Dict('gare'))
obj_id = CleanText(Dict('gare'), replace=[(' ', '-')])
class DeparturesPage2(HTMLPage):
def get_potential_arrivals(self):
arrivals = {}
for el in self.doc.xpath('//select[@id="gare_arrive_ambigu"]/option'):
arrivals[el.text] = el.attrib['value']
return arrivals
def get_station_id(self):
form = self.get_form('//form[@id="cfichehoraire"]')
return form['departExternalCode']
def init_departure(self, station):
form = self.get_form('//form[@id="cfichehoraire"]')
form['depart'] = station
form.submit()
def get_departures(self, arrival, date):
form = self.get_form('//form[@id="cfichehoraire"]')
form['arrive'] = arrival
if date:
form['jourHoraire'] = date.day
form['moiHoraire'] = '%s|%s' % (date.month, date.year)
form['heureHoraire'] = date.hour
form['minuteHoraire'] = date.minute
print form
form.submit()
class DeparturesPage(HTMLPage):
@method
class get_departures(TableElement):
head_xpath = u'//table[@class="etat_trafic"]/thead/tr/th[@scope="col"]/text()'
item_xpath = u'//table[@class="etat_trafic"]/tr'
col_type = u'Ligne'
col_info = u'Nom du train'
col_time = u'Heure de départ'
col_arrival = u'Destination'
col_plateform = u'Voie/quai'
col_id = u'Gares desservies'
class item(ItemElement):
klass = Departure
obj_time = DateTime(CleanText(TableCell('time')), LinearDateGuesser())
obj_type = DepartureTypeFilter(TableCell('type'))
obj_departure_station = CleanText(Env('station'))
obj_arrival_station = CleanText(TableCell('arrival'))
obj_information = CleanText(TableCell('info'))
obj_plateform = CleanText(TableCell('plateform'))
obj_id = Regexp(Link(Child(TableCell('id'))), '.*?numeroTrain=(.*?)&.*?')

View file

@ -1,65 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010-2011 Julien Hébert, Romain Bignon
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# 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 datetime
from weboob.capabilities import UserError
from weboob.tools.misc import to_unicode
from weboob.tools.browser import BasePage, BrokenPageError
__all__ = ['StationNotFound', 'DeparturesPage']
class StationNotFound(UserError):
pass
class DeparturesPage(BasePage):
def iter_routes(self):
try:
table = self.parser.select(self.document.getroot(), 'table.horaires3', 1)
except BrokenPageError:
raise StationNotFound('Station not found')
departure = self.parser.select(table, 'td.caption strong', 1).text
for tr in table.findall('tr'):
if len(tr.findall('td')) != 4:
continue
code_mission = self.parser.select(tr, 'td[headers=Code_de_mission] a', 1).text.strip()
time_s = self.parser.select(tr, 'td[headers=Heure_de_passage]', 1).text.strip().rstrip(u'\xa0*')
destination = self.parser.select(tr, 'td[headers=Destination]', 1).text.strip()
plateform = self.parser.select(tr, 'td[headers=Voie]', 1).text.strip()
late_reason = None
time = None
try :
time = datetime.datetime.combine(datetime.date.today(), datetime.time(*[int(x) for x in time_s.split(':')]))
except ValueError:
late_reason = time_s
self.logger.warning('Unable to parse datetime "%s"' % time_s)
yield {'type': to_unicode(code_mission),
'time': time,
'departure': to_unicode(departure),
'arrival': to_unicode(destination),
'late': datetime.time(),
'late_reason': late_reason,
'plateform': to_unicode(plateform)}

View file

@ -1,122 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010-2011 Romain Bignon
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# 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 re
import datetime
from weboob.capabilities.travel import RoadmapError
from weboob.tools.browser import BasePage
from weboob.tools.misc import to_unicode
from weboob.tools.mech import ClientForm
__all__ = ['RoadmapPage']
class RoadmapSearchPage(BasePage):
def search(self, departure, arrival, departure_time, arrival_time):
self.browser.select_form('formHiRecherche')
self.browser['lieuDepart'] = departure.encode('utf-8')
self.browser['lieuArrivee'] = arrival.encode('utf-8')
time = None
if departure_time:
self.browser['typeHeure'] = ['1']
time = departure_time
elif arrival_time:
self.browser['typeHeure'] = ['-1']
time = arrival_time
if time:
try:
self.browser['jour'] = ['%d' % time.day]
self.browser['mois'] = ['%02d/%d' % (time.month, time.year)]
self.browser['heure'] = ['%02d' % time.hour]
self.browser['minutes'] = ['%02d' % (time.minute - (time.minute%5))]
except ClientForm.ItemNotFoundError:
raise RoadmapError('Unable to establish a roadmap with %s time at "%s"' % ('departure' if departure_time else 'arrival', time))
self.browser.submit()
class RoadmapPage(BasePage):
def get_steps(self):
errors = []
for p in self.parser.select(self.document.getroot(), 'p.errors'):
if p.text:
errors.append(p.text.strip())
if len(errors) > 0:
raise RoadmapError('Unable to establish a roadmap: %s' % ', '.join(errors))
current_step = None
i = 0
for tr in self.parser.select(self.document.getroot(), 'table.horaires2 tbody tr'):
if not 'class' in tr.attrib:
continue
elif tr.attrib['class'] == 'trHautTroncon':
current_step = {}
current_step['id'] = i
i += 1
current_step['start_time'] = self.parse_time(self.parser.select(tr, 'td.formattedHeureDepart p', 1).text.strip())
current_step['line'] = to_unicode(self.parser.select(tr, 'td.rechercheResultatColumnMode img')[-1].attrib['alt'])
current_step['departure'] = to_unicode(self.parser.select(tr, 'td.descDepart p strong', 1).text.strip())
current_step['duration'] = self.parse_duration(self.parser.select(tr, 'td.rechercheResultatVertAlign', 1).text.strip())
elif tr.attrib['class'] == 'trBasTroncon':
current_step['end_time'] = self.parse_time(self.parser.select(tr, 'td.formattedHeureArrivee p', 1).text.strip())
current_step['arrival'] = to_unicode(self.parser.select(tr, 'td.descArrivee p strong', 1).text.strip())
yield current_step
def parse_time(self, time):
h, m = time.split('h')
return datetime.time(int(h), int(m))
def parse_duration(self, dur):
m = re.match('(\d+)min.', dur)
if m:
return datetime.timedelta(minutes=int(m.group(1)))
m = re.match('(\d+)h(\d+)', dur)
if m:
return datetime.timedelta(hours=int(m.group(1)),
minutes=int(m.group(2)))
class RoadmapConfirmPage(RoadmapPage):
def select(self, name, num):
try:
self.browser[name] = str(num)
except TypeError:
self.browser[name] = [str(num)]
def confirm(self):
self.browser.select_form('form1')
self.browser.set_all_readonly(False)
try:
self.select('idDepart', 1)
self.select('idArrivee', 1)
self.browser['modeTransport'] = ['0']
self.browser['trainRer'] = 'true'
self.browser['bus'] = 'false'
self.browser['tramway'] = 'true'
self.browser['bateau'] = 'false'
except ClientForm.ControlNotFoundError:
# We are already on the result page
return
else:
self.browser.submit()

View file

@ -1,346 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2010-2011 Julien Hébert, Romain Bignon
#
# This file is part of weboob.
#
# weboob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# weboob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
STATIONS = {
'BXN': u'BAGNEAUX SUR LOING',
'BJR': u'BOIS LE ROI',
'BOM': u'BOURRON MARLOTTE GREZ',
'BXI': u'BOUSSY ST ANTOINE',
'BNY': u'BRUNOY',
'CES': u'CESSON',
'CLY': u'CHANTILLY GOUVIEUX',
'CLX': u'CHATELET LES HALLES',
'CBV': u'COMBS LA VILLE QUINCY',
'COE': u'CORBEIL ESSONNES',
'CL': u'CREIL',
'DDI': u'DORDIVES',
'EVR': u'EVRY',
'EVC': u'EVRY COURCOURONNES',
'FFY': u'FERRIERES FONTENAY',
'FON': u'FONTAINEBLEAU AVON',
'GDS': u'GARE DU NORD',
'GAJ': u'GARGES SARCELLES',
'GOU': u'GOUSSAINVILLE',
'GBG': u'GRAND BOURG',
'GGG': u'GRIGNY CENTRE',
'JY': u'JUVISY',
'BBN': u'LA BORNE BLANCHE',
'BFX': u'LE BRAS DE FER',
'WEE': u'LE MEE',
'VD': u'LE VERT DE MAISONS',
'LNX': u'LES NOUES',
'LIU': u'LIEUSAINT MOISSY',
'LOV': u'LOUVRES',
'MFA': u'MAISONS ALFORT ALFORTVILLE',
'MEL': u'MELUN',
'MS': u'MONTARGIS',
'MTU': u'MONTEREAU',
'KRW': u'MONTGERON CROSNE',
'MKN': u'MONTIGNY SUR LOING',
'MOR': u'MORET VENEUX LES SABLONS',
'NSP': u'NEMOURS ST PIERRE',
'OBP': u'ORANGIS BOIS DE L EPINE',
'ORY': u'ORRY LA VILLE COYE LA FORET',
'PRF': u'PIERREFITTE STAINS',
'RIS': u'RIS ORANGIS',
'ZTN': u'SAVIGNY LE TEMPLE NANDY',
'SPP': u'SOUPPES CHÂTEAU LANDON',
'SDE': u'ST DENIS',
'SF': u'ST MAMMES',
'SFD': u'STADE DE FRANCE ST DENIS',
'SUR': u'SURVILLIERS FOSSES',
'TMR': u'THOMERY',
'VGS': u'VIGNEUX SUR SEINE',
'VP': u'VILLENEUVE PRAIRIE',
'VSG': u'VILLENEUVE ST GEORGES',
'VTV': u'VILLENEUVE TRIAGE',
'VIB': u'VILLIERS LE BEL GONESSE ARNOUVILLE',
'VWC': u'VIRY CHATILLON',
'YES': u'YERRES',
'ARW': u'ARGENTEUIL',
'AEH': u'AUBERGENVILLE ELISABETHVILLE',
'BEC': u'BECON LES BRUYERES',
'BCO': u'BOIS COLOMBES',
'CWJ': u'CHAVILLE RIVE DROITE',
'CLL': u'CLICHY LEVALLOIS',
'CBK': u'COLOMBES',
'CSH': u'CONFLANS SAINTE HONORINE',
'CPA': u'CORMEILLES EN PARISIS',
'KOU': u'COURBEVOIE',
'EPO': u'EPONE MEZIERES',
'ERA': u'ERAGNY NEUVILLE',
'ERE': u'ERMONT EAUBONNE',
'PSL': u'GARE ST LAZARE',
'HRY': u'HERBLAY',
'HAR': u'HOUILLES CARRIERES SUR SEINE',
'LDU': u'LA DEFENSE GARE SNCF',
'FMY': u'LA FRETTE MONTIGNY',
'LGK': u'LA GARENNE COLOMBES',
'LSD': u'LE STADE',
'VDO': u'LE VAL D OR',
'KVE': u'LES CLAIRIERES DE VERNEUIL',
'LMU': u'LES MUREAUX',
'LWA': u'LES VALLEES',
'MLF': u'MAISONS LAFFITTE',
'MTE': u'MANTES LA JOLIE',
'MTQ': u'MANTES STATION',
'MFL': u'MONTREUIL',
'NUN': u'NANTERRE UNIVERSITE',
'PSY': u'POISSY',
'PTC': u'PONT CARDINET',
'PSE': u'PONTOISE',
'PTX': u'PUTEAUX',
'SNN': u'SANNOIS',
'SVL': u'SARTROUVILLE',
'VDV': u'SEVRES VILLE D AVRAY',
'SCD': u'ST CLOUD',
'XOA': u'ST OUEN L AUMONE QUARTIER DE L EGLIS',
'MVH': u'SURESNES MONT VALERIEN',
'VDA': u'VAL D ARGENTEUIL',
'VET': u'VERNOUILLET VERNEUIL',
'VRD': u'VERSAILLES RIVE DROITE',
'VSW': u'VILLENNES SUR SEINE',
'VFD': u'VIROFLAY RIVE DROITE',
'ABL': u'ABLON',
'ARP': u'ARPAJON',
'ATH': u'ATHIS MONS',
'BFM': u'BIBLIOTHEQUE F. MITTERRAND',
'BIS': u'BIEVRES',
'BVI': u'BOULEVARD VICTOR',
'BY': u'BRETIGNY',
'BIH': u'BREUILLET BRUYERES LE CHATEL',
'BRW': u'BREUILLET VILLAGE',
'CPM': u'CHAMP DE MARS TOUR EIFFEL',
'CHV': u'CHAVILLE VELIZY',
'CAZ': u'CHILLY MAZARIN',
'CLR': u'CHOISY LE ROI',
'D': u'DOURDAN',
'ELY': u'EGLY',
'EYO': u'EPINAY SUR ORGE',
'GBI': u'GRAVIGNY BALIZY',
'IGY': u'IGNY',
'INV': u'INVALIDES',
'ISY': u'ISSY',
'ISP': u'ISSY VAL DE SEINE',
'IV': u'IVRY SUR SEINE',
'JVL': u'JAVEL',
'JAS': u'JOUY EN JOSAS',
'NG': u'LA NORVILLE ST GERMAIN LES ARPAJON',
'LAD': u'LES ARDOINES',
'LJU': u'LONGJUMEAU',
'MPU': u'MASSY PALAISEAU RER C',
'MFY': u'MEUDON VAL FLEURY',
'MDS': u'MUSEE D ORSAY',
'PJ': u'PETIT JOUY LES LOGES',
'PV': u'PETIT VAUX',
'PDM': u'PONT DE L ALMA',
'POA': u'PORCHEFONTAINE',
'SAO': u'SAVIGNY SUR ORGE',
'SXE': u'SERMAISE',
'SCW': u'ST CHERON',
'SHL': u'ST MICHEL NOTRE DAME',
'SHO': u'ST MICHEL SUR ORGE',
'SXG': u'STE GENEVIEVE DES BOIS',
'VBO': u'VAUBOYEN',
'VC': u'VERSAILLES CHANTIERS',
'VRG': u'VERSAILLES R G CHATEAU DE VERSAILLES',
'VRI': u'VILLENEUVE LE ROI',
'VFG': u'VIROFLAY RIVE GAUCHE',
'VY': u'VITRY SUR SEINE',
'BSO': u'BOURAY',
'CHK': u'CHAMARANDE',
'ETP': u'ETAMPES',
'ETY': u'ETRECHY',
'PZB': u'GARE D\'AUSTERLITZ',
'LYO': u'LARDY',
'MSX': u'MAROLLES EN HUREPOIX',
'SME': u'ST MARTIN D ETAMPES',
'CME': u'CHAMPAGNE SUR SEINE',
'CJR': u'CHARTRETTES',
'HER': u'HERICY',
'GPA': u'LA GRANDE PAROISSE',
'LYQ': u'LIVRY SUR SEINE',
'VSS': u'VERNOU SUR SEINE',
'VUN': u'VULAINES SUR SEINE SAMOREAU',
'PLY': u'GARE DE LYON',
'FPO': u'FONTAINE LE PORT',
'CJN': u'CHANGIS ST JEAN',
'CTH': u'CHATEAU THIERRY',
'CSG': u'CHELLES GOURNAY',
'CYZ': u'CHEZY SUR MARNE',
'CO': u'COULOMMIERS',
'EY': u'ESBLY',
'FMP': u'FAREMOUTIERS POMMEUSE',
'GCM': u'GUERARD LA CELLE SUR MORIN',
'LFJ': u'LA FERTE SOUS JOUARRE',
'LGY': u'LAGNY THORIGNY',
'MLB': u'MARLES EN BRIE',
'MEA': u'MEAUX',
'MOF': u'MORTCERF',
'MXK': u'MOUROUX',
'NAU': u'NANTEUIL SAACY',
'NAA': u'NOGENT L ARTAUD CHARLY',
'TOU': u'TOURNAN',
'TLP': u'TRILPORT',
'VAI': u'VAIRES TORCY',
'AEE': u'ASNIERES',
'AUU': u'AUBER',
'BQA': u'BRY SUR MARNE',
'BXG': u'BUSSY ST GEORGES',
'CGP': u'CHARLES DE GAULLE-ETOILE',
'GYN': u'GARE DE LYON',
'GAW': u'LA DEFENSE RER A',
'LQN': u'LOGNES',
'MVC': u'MARNE LA VALLEE CHESSY',
'NAF': u'NANTERRE PREFECTURE SNCF',
'NTN': u'NATION',
'NYP': u'NEUILLY PLAISANCE',
'NSL': u'NOISIEL',
'NYC': u'NOISY CHAMPS',
'NYG': u'NOISY LE GRAND MONT D EST',
'TOC': u'TORCY MARNE LA VALLEE',
'VDE': u'VAL D EUROPE',
'VFR': u'VAL DE FONTENAY RER A',
'VNC': u'VINCENNES',
'CJV': u'CERGY LE HAUT',
'CYP': u'CERGY PREFECTURE',
'CYC': u'CERGY ST CHRISTOPHE',
'CFD': u'CONFLANS FIN D OISE',
'NUE': u'NEUVILLE UNIVERSITE',
'RYR': u'AEROPORT CDG 2 TGV',
'ATW': u'ANTONY',
'ALC': u'AUBERVILLIERS LA COURNEUVE',
'AB': u'AULNAY SOUS BOIS',
'BAM': u'BLANC MESNIL',
'BQQ': u'BOURG LA REINE',
'BVJ': u'BURES SUR YVETTE',
'CUF': u'CITE UNIVERSITAIRE',
'CVW': u'COURCELLE SUR YVETTE',
'DFR': u'DENFERT ROCHEREAU',
'DRN': u'DRANCY',
'FMN': u'FONTAINE MICHALON',
'GIF': u'GIF SUR YVETTE',
'XBY': u'LA CROIX DE BERNY',
'HAQ': u'LA HACQUINIERE',
'LPN': u'LA PLAINE STADE DE FRANCE',
'LBT': u'LE BOURGET',
'GUW': u'LE GUICHET',
'BQC': u'LES BACONNETS',
'LZV': u'LOZERE',
'LXJ': u'LUXEMBOURG',
'MP': u'MASSY PALAISEAU RER B',
'MVP': u'MASSY VERRIERES RER B',
'ORS': u'ORSAY VILLE',
'PAX': u'PALAISEAU',
'PAW': u'PALAISEAU VILLEBON',
'PCX': u'PARC DE SCEAUX',
'PEX': u'PARC DES EXPOSITIONS',
'PWR': u'PORT ROYAL',
'BDE': u'SEVRAN BEAUDOTTES',
'XND': u'ST MICHEL NOTRE DAME',
'SNM': u'ST REMY LES CHEVREUSE',
'VPN': u'VILLEPINTE',
'RSY': u'AEROPORT CDG 1',
'ARK': u'ARCUEIL CACHAN',
'BGK': u'BAGNEUX',
'GTL': u'GENTILLY',
'LJA': u'LAPLACE',
'CVF': u'CHANTELOUP LES VIGNES',
'GGV': u'GARGENVILLE',
'IPO': u'ISSOU PORCHEVILLE',
'JUZ': u'JUZIERS',
'LIM': u'LIMAY',
'MHD': u'MEULAN HARDRICOURT',
'TPA': u'THUN LE PARADIS',
'TSS': u'TRIEL SUR SEINE',
'VXS': u'VAUX SUR SEINE',
'FNR': u'FONTENAY AUX ROSES',
'MY': u'MITRY CLAYE',
'RNS': u'ROBINSON',
'SKX': u'SCEAUX',
'SEV': u'SEVRAN LIVRY',
'VGL': u'VERT GALANT',
'VII': u'VILLEPARISIS MITRY LE NEUF',
'BOF': u'BOUFFEMONT MOISSELLES',
'DEU': u'DEUIL MONTMAGNY',
'DMO': u'DOMONT',
'ECZ': u'ECOUEN EZANVILLE',
'EPV': u'EPINAY VILLETANEUSE',
'PNB': u'GARE DU NORD',
'GRL': u'GROSLAY',
'LUZ': u'LUZARCHES',
'MSO': u'MONTSOULT MAFFLIERS',
'SLL': u'SARCELLES ST BRICE',
'SWY': u'SEUGY',
'VMS': u'VIARMES',
'VW': u'VILLAINES',
'CH': u'CHARTRES',
'CVI': u'CHAVILLE RIVE GAUCHE',
'CMA': u'CLAMART',
'CGW': u'COIGNIERES',
'DX': u'DREUX',
'EPN': u'EPERNON',
'FAF': u'FONTENAY LE FLEURY',
'GAQ': u'GARANCIERES LA QUEUE',
'GZA': u'GAZERAN',
'HOA': u'HOUDAN',
'JOY': u'JOUY',
'VYL': u'LA VERRIERE',
'LPE': u'LE PERRAY',
'LSI': u'LES ESSARTS LE ROI',
'MTN': u'MAINTENON',
'MBR': u'MARCHEZAIS BROUE',
'MDN': u'MEUDON',
'MLM': u'MONTFORT L AMAURY MERE',
'OGB': u'ORGERUS BEHOUST',
'PMP': u'PARIS MONTPARNASSE',
'PG': u'PLAISIR GRIGNON',
'PIE': u'PLAISIR LES CLAYES',
'RBT': u'RAMBOUILLET',
'SVR': u'SEVRES RIVE GAUCHE',
'SCR': u'ST CYR',
'SPI': u'ST PIAT',
'SQY': u'ST QUENTIN EN YVELINES',
'TAE': u'TACOIGNIERES RICHEBOURG',
'TVO': u'TRAPPES',
'VMK': u'VANVES MALAKOFF',
'VEP': u'VILLEPREUX LES CLAYES',
'VEH': u'VILLIERS NEAUPHLE PONTCHARTRAIN',
'CEG': u'CHAMP DE COURSES D ENGHIEN',
'CPO': u'CHAMPAGNE SUR OISE',
'EN': u'ENGHIEN LES BAINS',
'ERT': u'ERMONT EAUBONNE',
'ERM': u'ERMONT HALTE',
'FPN': u'FREPILLON',
'GNX': u'GROS NOYER ST PRIX',
'IAP': u'L ISLE ADAM PARMAIN',
'LBJ': u'LA BARRE ORMESSON',
'MLV': u'MERIEL',
'MWO': u'MERY SUR OISE',
'PEB': u'PERSAN BEAUMONT',
'SLF': u'ST LEU LA FORET',
'TVY': u'TAVERNY',
'VMD': u'VALMONDOIS',
'VCX': u'VAUCELLES',
'MJM': u'MAREIL SUR MAULDRE',
'MAE': u'MAULE',
'NZL': u'NEZEL AULNAY',
'PAA': u'GARE DE LYON',
}

View file

@ -26,17 +26,20 @@ from weboob.tools.test import BackendTest
class TransilienTest(BackendTest):
BACKEND = 'transilien'
def test_departures(self):
stations = list(self.backend.iter_station_search('defense'))
def test_stations(self):
stations = list(self.backend.iter_station_search('aul'))
self.assertTrue(len(stations) > 0)
def test_departures(self):
stations = list(self.backend.iter_station_search('aul'))
self.assertTrue(len(stations) > 0)
list(self.backend.iter_station_departures(stations[0].id))
def test_roadmap(self):
filters = RoadmapFilters()
roadmap = list(self.backend.iter_roadmap('Puteaux', u'École Militaire', filters))
roadmap = list(self.backend.iter_roadmap('aul', u'aub', filters))
self.assertTrue(len(roadmap) > 0)
filters.arrival_time = datetime.datetime.now() + datetime.timedelta(days=1)
roadmap = list(self.backend.iter_roadmap('Puteaux', u'Aulnay-sous-Bois', filters))
roadmap = list(self.backend.iter_roadmap('aul', u'bag', filters))
self.assertTrue(len(roadmap) > 0)