TransseeAPI / app.py
42Cummer's picture
Update app.py
f034e6c verified
raw
history blame
6.49 kB
from flask import Flask, render_template, request, jsonify
from flask_cors import CORS
import re
import requests
from bs4 import BeautifulSoup
import tempfile
import os
app = Flask(__name__)
CORS(app)
import re
import requests
from bs4 import BeautifulSoup
from flask import jsonify
@app.route('/routelist', methods=['GET'])
def getRouteList():
url = "https://www.transsee.ca/routelist?a=ttc&ShowAll=1"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
'Referer': 'https://www.transsee.ca/',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
except Exception as e:
return jsonify({"error": f"Failed to fetch route list: {e}"}), 500
soup = BeautifulSoup(response.text, "html.parser")
routes = {}
for rid in range(7, 204): # all conventional routes
tag = soup.find("p", {"id": str(rid)})
if tag and tag.text.strip():
# Clean text:
text = tag.get_text(strip=True)
# Remove leading symbols like "*" or "== $0"
text = re.sub(r"^[^A-Za-z0-9]+", "", text) # strip non-alphanumeric at start
text = re.sub(r"\s*==.*$", "", text) # strip trailing "== $0" or similar
text = re.sub(r"\s+", " ", text).strip() # collapse spaces
# Replace dash between number and name with space (e.g., "26-Dupont" -> "26 Dupont")
text = re.sub(r'(\d+)-([A-Za-z])', r'\1 \2', text)
routes[rid] = text
for rid in range(300, 399): # all blue night routes
tag = soup.find("p", {"id": str(rid)})
if tag and tag.text.strip():
# Clean text:
text = tag.get_text(strip=True)
# Remove leading symbols like "*" or "== $0"
text = re.sub(r"^[^A-Za-z0-9]+", "", text) # strip non-alphanumeric at start
text = re.sub(r"\s*==.*$", "", text) # strip trailing "== $0" or similar
text = re.sub(r"\s+", " ", text).strip() # collapse spaces
# Replace dash between number and name with space (e.g., "26-Dupont" -> "26 Dupont")
text = re.sub(r'(\d+)-([A-Za-z])', r'\1 \2', text)
if not 'Night Bus' in text: continue
routes[rid] = text
for rid in range(900, 999): # all express routes
tag = soup.find("p", {"id": str(rid)})
if tag and tag.text.strip():
# Clean text:
text = tag.get_text(strip=True)
# Remove leading symbols like "*" or "== $0"
text = re.sub(r"^[^A-Za-z0-9]+", "", text) # strip non-alphanumeric at start
text = re.sub(r"\s*==.*$", "", text) # strip trailing "== $0" or similar
text = re.sub(r"\s+", " ", text).strip() # collapse spaces
# Replace dash between number and name with space (e.g., "26-Dupont" -> "26 Dupont")
text = re.sub(r'(\d+)-([A-Za-z])', r'\1 \2', text)
routes[rid] = text
return jsonify(routes)
@app.route('/listvehiclesbyroute', methods=['POST'])
def listVehiclesByRoute():
data = request.get_json()
if not data or "route" not in data:
return jsonify({"error": "Missing route parameter"}), 400
route = data["route"]
url = f"https://www.transsee.ca/routeveh?a=ttc&r={route}"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
'Referer': 'https://www.transsee.ca/',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
except Exception as e:
return jsonify({"error": f"Failed to fetch route list: {e}"}), 500
soup = BeautifulSoup(response.text, "html.parser")
core_div = soup.find("div", class_="core")
if not core_div:
return jsonify({"error": "No vehicles found"}), 404
vehicles = []
for p in core_div.find_all("p", id=True):
vehicle_id = p.find("a").get_text(strip=True) if p.find("a") else None
spans = p.find_all("span")
delay = None
if spans:
first_text = spans[0].get_text(strip=True).lower()
if "waiting" in first_text and len(spans) > 1:
delay = spans[1].get_text(strip=True)
else:
delay = spans[0].get_text(strip=True)
time = p.find("time").get_text(strip=True) if p.find("time") else None
direction = None
destination = None
for part in p.stripped_strings:
if part.startswith("going"):
direction = part
elif "to " in part: # destination line
destination = part
late = delay.split(' ')[-1].lower() == 'behind'
delay_value = delay.split(' ')[0]
# Convert delay from hh:mm:ss to mm:ss format
if ":" in delay_value:
parts = delay_value.split(":")
if len(parts) == 3: # hh:mm:ss format
try:
h, m, s = parts
# Convert to mm:ss by adding hours to minutes
total_minutes = int(h) * 60 + int(m)
delay_value = f"{total_minutes}:{s}"
except:
pass
# If it's mm:ss format, keep as is
delay = ("-" if late else "+") + delay_value
vehicles.append({
"vehicle_id": vehicle_id,
"delay": delay,
"time": time,
"branch": direction.split(' ')[-1],
"destination": destination
})
return jsonify({
"route": route,
"vehicles": vehicles
})
@app.route('/', methods=['GET'])
def health_check():
return 'Backend is running!', 200
if __name__ == '__main__':
app.run(debug=True, port=5000)