Implement connection finder. All features of oebbApi now implemented.
This commit is contained in:
parent
f99b6cf237
commit
caca14c66a
|
@ -17,9 +17,9 @@ class Station:
|
||||||
return self.xcoord
|
return self.xcoord
|
||||||
|
|
||||||
class Service:
|
class Service:
|
||||||
def __init__(self, name, svtype, depst, deptime, arrst, arrtime, deppf = None, currdep = None, arrpf = None, curarr = None, img = None, url = None):
|
def __init__(self, name, depst, deptime, arrst, arrtime, dest = None, deppf = None, currdep = None, arrpf = None, curarr = None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.svtype = svtype
|
self.dest = dest
|
||||||
self.depst = depst
|
self.depst = depst
|
||||||
self.deptime = deptime
|
self.deptime = deptime
|
||||||
self.arrst = arrst
|
self.arrst = arrst
|
||||||
|
@ -28,14 +28,14 @@ class Service:
|
||||||
self.currdep = currdep
|
self.currdep = currdep
|
||||||
self.arrpf = arrpf
|
self.arrpf = arrpf
|
||||||
self.curarr = curarr
|
self.curarr = curarr
|
||||||
self.img = img
|
|
||||||
self.url = url
|
def duration():
|
||||||
|
return self.arrtime - self.deptime
|
||||||
|
|
||||||
class Connection:
|
class Connection:
|
||||||
def __init__(self, buyurl = None, statusurl = None):
|
def __init__(self, buyurl = None):
|
||||||
self.services = []
|
self.services = []
|
||||||
self.buyurl = buyurl
|
self.buyurl = buyurl
|
||||||
self.statusurl = statusurl
|
|
||||||
|
|
||||||
def addService(self, service):
|
def addService(self, service):
|
||||||
self.services.append(service)
|
self.services.append(service)
|
||||||
|
@ -75,3 +75,9 @@ class Connection:
|
||||||
return self.services[-1].currarr
|
return self.services[-1].currarr
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def duration(self):
|
||||||
|
try:
|
||||||
|
return self.services[-1].arrtime - self.services[0].deptime
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
14
main.py
14
main.py
|
@ -1,5 +1,6 @@
|
||||||
import cgi
|
import cgi
|
||||||
import datetime
|
import datetime
|
||||||
|
import pytz
|
||||||
|
|
||||||
import workers.conn
|
import workers.conn
|
||||||
import workers.val
|
import workers.val
|
||||||
|
@ -36,10 +37,11 @@ def application(env, re):
|
||||||
yield "\"from\" and \"to\" values are required for this type of request.".encode()
|
yield "\"from\" and \"to\" values are required for this type of request.".encode()
|
||||||
return
|
return
|
||||||
|
|
||||||
count = args["count"][0] if "count" in args and args["count"] else 3
|
count = args["count"][0] if "count" in args and args["count"] else 1
|
||||||
date = args["date"][0] if "date" in args and args["date"] else datetime.datetime.strftime(datetime.datetime.now(),"%d.%m.%Y")
|
date = args["date"][0] if "date" in args and args["date"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%d.%m.%Y")
|
||||||
time = args["time"][0] if "time" in args and args["time"] else datetime.datetime.strftime(datetime.datetime.now(),"%H:%M")
|
time = args["time"][0] if "time" in args and args["time"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%H:%M")
|
||||||
mode = True if "mode" in args and args["mode"] and args["mode"][0].lower() == "arr" else False
|
mode = True if "mode" in args and args["mode"] and args["mode"][0].lower() == "arr" else False
|
||||||
|
details = True if "details" in args else False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
count = int(count)
|
count = int(count)
|
||||||
|
@ -60,16 +62,18 @@ def application(env, re):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
output = workers.conn.worker(frm, to, count, outtime, mode)
|
output = workers.conn.worker(frm, to, count, outtime, mode, details)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
re("500 Internal Server Error", [])
|
re("500 Internal Server Error", [])
|
||||||
yield "<h1>500 Internal Server Error</h1>".encode()
|
yield "<h1>500 Internal Server Error</h1>".encode()
|
||||||
if "debug" in args:
|
if "debug" in args:
|
||||||
yield str(e).encode()
|
yield str(e).encode()
|
||||||
|
raise
|
||||||
return
|
return
|
||||||
|
|
||||||
re("200 OK", [])
|
re("200 OK", [])
|
||||||
return output.encode()
|
yield output.encode()
|
||||||
|
return
|
||||||
|
|
||||||
elif rtype.lower() in ["val", "validate"]:
|
elif rtype.lower() in ["val", "validate"]:
|
||||||
try:
|
try:
|
||||||
|
|
215
workers/conn.py
215
workers/conn.py
|
@ -1,9 +1,15 @@
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import requests
|
import requests
|
||||||
import datetime
|
import datetime
|
||||||
import workers.val
|
import pytz
|
||||||
|
|
||||||
def connRequest(frm, to, count = 3, time = datetime.datetime.now(), mode = False):
|
import workers.val
|
||||||
|
from classes import *
|
||||||
|
|
||||||
|
def getStation(name):
|
||||||
|
return list(workers.val.validateName(name))[0]
|
||||||
|
|
||||||
|
def connRequest(frm, to, count = 3, time = datetime.datetime.now(), mode = False, details = False):
|
||||||
outdate = datetime.datetime.strftime(time,"%d.%m.%Y")
|
outdate = datetime.datetime.strftime(time,"%d.%m.%Y")
|
||||||
outtime = datetime.datetime.strftime(time,"%H:%M")
|
outtime = datetime.datetime.strftime(time,"%H:%M")
|
||||||
|
|
||||||
|
@ -13,11 +19,204 @@ def connRequest(frm, to, count = 3, time = datetime.datetime.now(), mode = False
|
||||||
if "GO_conViewMode=outward" not in source:
|
if "GO_conViewMode=outward" not in source:
|
||||||
raise ValueError("No connection found.")
|
raise ValueError("No connection found.")
|
||||||
|
|
||||||
return source
|
juha = BeautifulSoup(source, "html5lib")
|
||||||
|
|
||||||
|
if details:
|
||||||
|
for a in juha.findAll("a"):
|
||||||
|
if a.get("href") and "HWAI=CONNECTION$" in a.get("href"):
|
||||||
|
dpage = a.get("href")
|
||||||
|
|
||||||
def getStation(name):
|
ssource = requests.get(dpage).text
|
||||||
return list(workers.val.validateName(name))[0]
|
suppe = BeautifulSoup(ssource, "html5lib")
|
||||||
|
|
||||||
|
for i in range(0, count):
|
||||||
|
cont = suppe.find("tr", id="trC0-%i" % i)
|
||||||
|
if not cont:
|
||||||
|
break
|
||||||
|
|
||||||
def worker(frm, to, count = 3, time = datetime.datetime.now(), mode = False):
|
buyurl = None
|
||||||
source = connRequest(frm, to, count, time, mode)
|
|
||||||
conns = dissem(source)
|
for url in cont.findAll("a"):
|
||||||
|
if url.get("href") and "https://tickets.oebb.at/de/ticket/ticket?" in url.get("href"):
|
||||||
|
buyurl = url.get("href")
|
||||||
|
|
||||||
|
conn = Connection(buyurl)
|
||||||
|
|
||||||
|
lines = cont.findAll("tr", { "class": "tpDetails" })[1:]
|
||||||
|
cdate = None
|
||||||
|
|
||||||
|
for line in range(0, len(lines), 3):
|
||||||
|
serv = lines[line:line + 3]
|
||||||
|
dep = serv[0]
|
||||||
|
arr = serv[1]
|
||||||
|
det = serv[2]
|
||||||
|
|
||||||
|
depst = list(workers.val.validateName(dep.find("td", { "class": "station" }).findAll("a")[0].string))[0]
|
||||||
|
depdate = dep.find("td", { "class": "date" }).string.strip() or cdate
|
||||||
|
deptime = dep.find("td", { "class": "timeValue" }).find("span").string.split()[1].strip()
|
||||||
|
depprog = (dep.find("span", { "class": "prognosis" }).find("span") or dep.find("span", { "class": "prognosis" })).string.strip() or None
|
||||||
|
depplat = (dep.find("td", { "class": "platform" }).find("span") or dep.find("td", { "class": "platform" })).string.strip() or None
|
||||||
|
|
||||||
|
walk = dep.find("img", { "class": "product" }).get("src") == "/img/vs_oebb/fuss_pic.gif"
|
||||||
|
name = dep.find("img", { "class": "product" }).get("alt") if not walk else "Walk"
|
||||||
|
|
||||||
|
if not walk:
|
||||||
|
purl = dep.find("td", { "class": "product" }).find("a").get("href")
|
||||||
|
psource = requests.get(purl).text
|
||||||
|
|
||||||
|
zuppa = BeautifulSoup(psource, "html5lib")
|
||||||
|
dest = list(workers.val.validateName(zuppa.findAll("div", { "class": "block" })[2].text.split(":")[1].strip()))[0]
|
||||||
|
|
||||||
|
arrst = list(workers.val.validateName(arr.find("td", { "class": "station" }).findAll("a")[0].string))[0]
|
||||||
|
arrdate = (arr.find("td", { "class": "date" }).find("span") or arr.find("td", { "class": "date" })).string.strip() or depdate
|
||||||
|
arrtime = arr.find("td", { "class": "timeValue" }).find("span").string.split()[1].strip()
|
||||||
|
arrprog = (arr.find("span", { "class": "prognosis" }).find("span") or arr.find("span", { "class": "prognosis" })).string.strip() or None
|
||||||
|
arrplat = (arr.find("td", { "class": "platform" }).find("span") or arr.find("td", { "class": "platform" })).string.strip() or None
|
||||||
|
|
||||||
|
depts = datetime.datetime.strptime("%s %s" % (depdate, deptime), "%d.%m.%Y %H:%M")
|
||||||
|
arrts = datetime.datetime.strptime("%s %s" % (arrdate, arrtime), "%d.%m.%Y %H:%M")
|
||||||
|
|
||||||
|
depprog = deptime if depprog == "pünktlich" else depprog
|
||||||
|
arrprog = arrtime if arrprog == "pünktlich" else arrprog
|
||||||
|
|
||||||
|
cdate = arrdate
|
||||||
|
|
||||||
|
svc = Service(name, depst, depts, arrst, arrts, dest, depplat, depprog, arrplat, arrprog)
|
||||||
|
conn.addService(svc)
|
||||||
|
|
||||||
|
yield conn
|
||||||
|
|
||||||
|
else:
|
||||||
|
for i in range(0, count):
|
||||||
|
det = juha.find("tr", id="trOverviewC0-%i" % i)
|
||||||
|
if not det:
|
||||||
|
break
|
||||||
|
|
||||||
|
stations = det.find("td", { "class": "station" }).findAll("div")
|
||||||
|
depst = getStation(stations[0].text.strip())
|
||||||
|
arrst = getStation(stations[-1].text.strip())
|
||||||
|
|
||||||
|
dates = det.find("td", { "class": "date" }).text.split()
|
||||||
|
depdate = dates[0]
|
||||||
|
try:
|
||||||
|
arrdate = dates[1]
|
||||||
|
except:
|
||||||
|
arrdate = depdate
|
||||||
|
|
||||||
|
times = det.find("div", { "class": "planed" }).text
|
||||||
|
deptime = times.split()[0]
|
||||||
|
arrtime = times.split()[2]
|
||||||
|
|
||||||
|
projections = det.find("div", { "class": "prognosis" })
|
||||||
|
curdep = None
|
||||||
|
curarr = None
|
||||||
|
|
||||||
|
depts = datetime.datetime.strptime("%s %s" % (depdate, deptime), "%d.%m.%Y %H:%M")
|
||||||
|
arrts = datetime.datetime.strptime("%s %s" % (arrdate, arrtime), "%d.%m.%Y %H:%M")
|
||||||
|
|
||||||
|
name = "/".join([img.get("title") for img in det.findAll("img", { "class": "product" })])
|
||||||
|
|
||||||
|
ticketurl = det.find("td", { "class": "fares" }).find("a").get("href")
|
||||||
|
|
||||||
|
svc = Service(name, depst, depts, arrst, arrts, currdep = curdep, curarr = curarr)
|
||||||
|
con = Connection(ticketurl)
|
||||||
|
|
||||||
|
con.addService(svc)
|
||||||
|
|
||||||
|
yield con
|
||||||
|
|
||||||
|
def worker(frm, to, count = 3, time = datetime.datetime.now(pytz.timezone("Europe/Vienna")), mode = False, details = False):
|
||||||
|
conns = connRequest(getStation(frm), getStation(to), count, time, mode, details)
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
output = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<connections>
|
||||||
|
"""
|
||||||
|
|
||||||
|
for conn in conns:
|
||||||
|
hrs, scs = divmod(conn.duration().total_seconds(), 3600)
|
||||||
|
mns, rmd = divmod(scs, 60)
|
||||||
|
|
||||||
|
chg = max(len([service for service in conn.services if service.name != "Walk"]) - 1, 0) if details else max(len([service for service in conn.services[0].name.split("/") if service != "Walk"]) - 1, 0)
|
||||||
|
|
||||||
|
ddt = datetime.datetime.strftime(conn.deptime(), "%d.%m.%Y")
|
||||||
|
dtm = datetime.datetime.strftime(conn.deptime(), "%H:%M")
|
||||||
|
|
||||||
|
adt = datetime.datetime.strftime(conn.arrtime(), "%d.%m.%Y")
|
||||||
|
atm = datetime.datetime.strftime(conn.arrtime(), "%H:%M")
|
||||||
|
|
||||||
|
output += """ <connection id='%i'>
|
||||||
|
<from>
|
||||||
|
<name>%s</name>
|
||||||
|
<id>%s</id>
|
||||||
|
</from>
|
||||||
|
<to>
|
||||||
|
<name>%s</name>
|
||||||
|
<id>%s</id>
|
||||||
|
</to>
|
||||||
|
<details>
|
||||||
|
<departure>
|
||||||
|
<date>%s</date>
|
||||||
|
<time>%s</time>
|
||||||
|
</departure>
|
||||||
|
<arrival>
|
||||||
|
<date>%s</date>
|
||||||
|
<time>%s</time>
|
||||||
|
</arrival>
|
||||||
|
<duration>%s</duration>
|
||||||
|
<changes>%i</changes>
|
||||||
|
</details>
|
||||||
|
<services>
|
||||||
|
""" % (i, conn.depst().name, conn.depst().useId(), conn.arrst().name, conn.arrst().useId(), ddt, dtm, adt, atm, "%i:%i" % (hrs, mns), chg)
|
||||||
|
|
||||||
|
j = 0
|
||||||
|
|
||||||
|
for service in conn.services:
|
||||||
|
output += """ <service id='%i'>
|
||||||
|
<name>%s</name>
|
||||||
|
<departure>
|
||||||
|
<station>
|
||||||
|
<name>%s</name>
|
||||||
|
<id>%s</id>
|
||||||
|
</station>
|
||||||
|
<date>%s</date>
|
||||||
|
<time>%s</time>
|
||||||
|
""" % (j, service.name, service.depst.name, service.depst.useId(), datetime.datetime.strftime(service.deptime,"%d.%m.%Y"), datetime.datetime.strftime(service.deptime, "%H:%M"))
|
||||||
|
|
||||||
|
if service.currdep:
|
||||||
|
output += " <current>%s</current>\n" % service.currdep
|
||||||
|
|
||||||
|
if service.deppf:
|
||||||
|
output += " <platform>%s</platform>\n" % service.deppf
|
||||||
|
|
||||||
|
output += """ </departure>
|
||||||
|
<arrival>
|
||||||
|
<station>
|
||||||
|
<name>%s</name>
|
||||||
|
<id>%s</id>
|
||||||
|
</station>
|
||||||
|
<date>%s</date>
|
||||||
|
<time>%s</time>
|
||||||
|
""" % (service.arrst.name, service.arrst.useId(), datetime.datetime.strftime(service.arrtime, "%d.%m.%Y"), datetime.datetime.strftime(service.arrtime, "%H:%M"))
|
||||||
|
|
||||||
|
if service.curarr:
|
||||||
|
output += " <current>%s</current>\n" % service.curarr
|
||||||
|
|
||||||
|
if service.arrpf:
|
||||||
|
output += " <platform>%s</platform>\n" % service.arrpf
|
||||||
|
|
||||||
|
output += """ </arrival>
|
||||||
|
</service>
|
||||||
|
"""
|
||||||
|
|
||||||
|
j += 1
|
||||||
|
|
||||||
|
output += """ </services>
|
||||||
|
</connection>
|
||||||
|
"""
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
output += """</connections>"""
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
Loading…
Reference in a new issue