+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
from BeautifulSoup import BeautifulSoup, NavigableString
from urllib2 import urlopen
from urllib import urlencode
from datetime import datetime, time
from textwrap import wrap
import argparse
+import sys
+import os.path
POSITION_TYPES = ('stop', 'address', 'poi')
+TIMEFORMAT = '%H:%M'
+DEBUGLOG = os.path.expanduser('~/gotoVienna.debug')
-class ParserException(Exception):
+class ParserError(Exception):
- def __init__(self, msg = 'Parser error'):
+ def __init__(self, msg='Parser error'):
self.message = msg
class PageType:
destination, destination_type = destination_tuple
if not origin_type in POSITION_TYPES or\
not destination_type in POSITION_TYPES:
- raise ParserException('Invalid position type')
+ raise ParserError('Invalid position type')
post = settings.search_post
post['name_origin'] = origin
post['itdDateDayMonthYear'] = dtime.strftime('%d.%m.%Y')
post['itdTime'] = dtime.strftime('%H:%M')
params = urlencode(post)
- return urlopen('%s?%s' % (settings.action, params))
+ url = '%s?%s' % (settings.action, params)
+
+ try:
+ f = open(DEBUGLOG, 'a')
+ f.write(url + '\n')
+ f.close()
+ except:
+ print 'Unable to write to DEBUGLOG: %s' % DEBUGLOG
+
+ return urlopen(url)
class sParser:
"""
def __init__(self, html):
- self.bs = BeautifulSoup(html)
+ self.soup = BeautifulSoup(html)
def check_page(self):
- if self.bs.find('form', {'id': 'form_efaresults'}):
+ if self.soup.find('form', {'id': 'form_efaresults'}):
return PageType.RESULT
- if self.bs.find('div', {'class':'form_error'}):
+ if self.soup.find('div', {'class':'form_error'}):
return PageType.CORRECTION
return PageType.UNKNOWN
def get_correction(self):
- nlo = self.bs.find('select', {'id': 'nameList_origin'})
- nld = self.bs.find('select', {'id': 'nameList_destination'})
+ nlo = self.soup.find('select', {'id': 'nameList_origin'})
+ nld = self.soup.find('select', {'id': 'nameList_destination'})
- if not nlo or not nld:
+ if not nlo and not nld:
raise ParserError('Unable to parse html')
- origin = nlo.findAll('option')
- destination = nld.findAll('option')
-
- if not origin:
+ if nlo:
+ origin = map(lambda x: x.text, nlo.findAll('option'))
+ else:
origin = []
- if not destination:
+ if nld:
+ destination = map(lambda x: x.text, nld.findAll('option'))
+ else:
destination = []
return (origin, destination)
def get_result(self):
- return rParser(str(self.bs))
+ return rParser(str(self.soup))
'date': rParser.get_date(x),
'time': rParser.get_time(x),
'duration': rParser.get_duration(x), # grab duration
- 'change': rParser.get_change(x),
+ 'change': rParser.get_change(x),
'price': rParser.get_price(x),
},
rows)
else:
- raise ParserError('Unable to parse details')
+ raise ParserError('Unable to parse overview')
return overview
try:
self._overview = self._parse_overview()
except AttributeError:
- f = open('DEBUG', 'w')
+ f = open(DEBUGLOG, 'w')
f.write(str(self.soup))
f.close()
return self._overview
if __name__ == '__main__':
- pass
\ No newline at end of file
+ parser = argparse.ArgumentParser(description='Get public transport route for Vienna')
+ parser.add_argument('-o', metavar='name', type=str, help='origin', required=True)
+ parser.add_argument('-d', metavar='name', type=str, help='destination', required=True)
+ parser.add_argument('-ot', metavar='type', type=str, help='origin type: %s' % ' | '.join(POSITION_TYPES), default='stop', choices=POSITION_TYPES)
+ parser.add_argument('-dt', metavar='type', type=str, help='destination type: %s' % ' | '.join(POSITION_TYPES), default='stop', choices=POSITION_TYPES)
+
+ args = parser.parse_args()
+ html = search((args.o, args.ot), (args.d, args.dt)).read()
+
+ parser = sParser(html)
+ state = parser.check_page()
+
+ if state == PageType.CORRECTION:
+ try:
+ cor = parser.get_correction()
+ if cor[0]:
+ print
+ print '* Origin ambiguous:'
+ lo = None
+ while not lo or not lo.isdigit() or int(lo) > len(cor[0]):
+ i = 1
+ for c in cor[0]:
+ print '%d. %s' % (i, c)
+ i += 1
+ lo = sys.stdin.readline().strip()
+
+ args.o = cor[0][int(lo) - 1]
+
+ if cor[1]:
+ print
+ print '* Destination ambiguous:'
+ ld = None
+ while not ld or not ld.isdigit() or int(ld) > len(cor[1]):
+ j = 1
+ for c in cor[1]:
+ print '%d. %s' % (j, c)
+ j += 1
+ ld = sys.stdin.readline().strip()
+
+ args.d = cor[1][int(ld) - 1]
+
+ html = search((args.o.encode('UTF-8'), args.ot), (args.d.encode('UTF-8'), args.dt)).read()
+
+ parser = sParser(html)
+ state = parser.check_page()
+
+ except ParserError:
+ print 'PANIC at correction page'
+
+ if state == PageType.RESULT:
+ parser = rParser(html)
+ try:
+ overviews = parser.overview
+ details = parser.details
+ l = ''
+ while not l == 'q':
+ for r in range(len(overviews)):
+ print '%d. [%s] %s-%s (%s)' % (r + 1, overviews[r]['date'], overviews[r]['time'][0], overviews[r]['time'][1], overviews[r]['duration'])
+ print 'q. Quit'
+ l = sys.stdin.readline().strip()
+ print
+ print '~' * 100
+
+ if l.isdigit() and int(l) <= len(details):
+ for detail in details[int(l) - 1]:
+ if detail['time'] and detail['station']:
+ time = '%s - %s' % (detail['time'][0].strftime(TIMEFORMAT), detail['time'][1].strftime(TIMEFORMAT))
+ print '[%s] %s\n%s' % (time, ' -> '.join(detail['station']), '\n'.join(detail['info']))
+ else:
+ print '\n'.join(detail['info'])
+ print '-' * 100
+ print
+
+ except ParserError:
+ print 'parsererror'
+
+ elif state == PageType.UNKNOWN:
+ print 'PANIC unknown result'