An unofficial Python wrapper of the BUBT Routine API + a robust web scraper and PDF extractor for getting routine data.
Project description
🎓 BUBT RoutinePy
Part of Project "Harukaze🍃"
Overview
An unofficial Python wrapper of the BUBT Routine API, seamlessly integrated with a robust web scraper and PDF extractor for getting routine data.
🌟 Features
-
Unofficial & Reverse-Engineered: Built through reverse-engineering of BUBT Routine API endpoints
-
Robust Web Scraper: Extracts routine data directly from the BUBT website, supporting both HTML and PDF formats.
-
Command-Line Interface (CLI): Offers a CLI version for easy routine data retrieval from the terminal (with different outputs like
table,text,json). -
Caching Mechanism: Caches HTML and PDF files to optimize performance and reduce overhead on Annex (it's already slow enough).
-
Data Normalization: Consistent output format across all sources (API/HTML/PDF)
⚡ Installation
Stable Version (Recommended)
uv add bubt-routinepy
Or the usual
pip install bubt-routinepy
Development Version
pip install git+https://github.com/kurtnettle/bubt-routinepy.git@master
📝 Usage
CLI
routinepy --routine-type class --program-code 006 --intake 50 --section 1
output (default):
+------------------------------------------------------------------------+
| Class Routine (50-1) |
+----------------------+---------+---------+---------+---------+---------+
| Time | sun | mon | tues | wednes | thurs |
+----------------------+---------+---------+---------+---------+---------+
| 08:00 AM to 09:15 AM | CSE 320 | | | | |
| | WMO | | | | |
| | B2/416 | | | | |
| 09:15 AM to 10:30 AM | CSE 320 | | CSE 328 | | |
| | WMO | | MRG | | |
| | B2/416 | | B2/518 | | |
| 10:30 AM to 11:45 AM | CSE 351 | | CSE 407 | | |
| | SAM | | NMP | | |
| | B2/710 | | B2/710 | | |
| 11:45 AM to 01:00 PM | | CSE 327 | CSE 417 | CSE 417 | |
| | | MRG | ADSK | ADSK | |
| | | B2/709 | B2/710 | B2/909 | |
| 01:30 PM to 02:45 PM | | CSE 418 | | CSE 352 | |
| | | ADSK | | SAM | |
| | | B2/417 | | B2/420 | |
| 02:45 PM to 04:00 PM | | CSE 418 | | CSE 352 | CSE 319 |
| | | ADSK | | SAM | WMO |
| | | B2/417 | | B2/420 | B2/709 |
| 04:00 PM to 05:15 PM | | CSE 319 | | CSE 327 | CSE 407 |
| | | WMO | | MRG | NMP |
| | | B2/318 | | B2/710 | B2/709 |
| 05:15 PM to 06:30 PM | | | | | CSE 351 |
| | | | | | SAM |
| | | | | | B2/709 |
+----------------------+---------+---------+---------+---------+---------+
Or if you prefer JSON
routinepy --routine-type class --program-code 006 --intake 50 --section 1 --format json
Output:
[{"week_day": "sun", "period_time": "08:00 AM to 09:15 AM", "intake": "50", "section": "1", "faculty_code": "WMO", "building": "2", "room": "416", "course_code": "CSE 320", "shift_time": "Day"},
... ,
... ,
... ,
{"week_day": "thurs", "period_time": "05:15 PM to 06:30 PM", "intake": "50", "section": "1", "faculty_code": "SAM", "building": "2", "room": "709", "course_code": "CSE 351", "shift_time": "Day"}]
[!TIP] Check documentation for complete CLI reference
As a Library
1. Initializing Clients
# For scraping functionality
from routinepy.lib import ScraperClient
scraper = ScraperClient()
# For API functionality
from routinepy.lib import ApiClient
api = ApiClient()
2. Let's get the routine of CSE Dept Intake 50 and Section 1
from routinepy.lib.enums import ProgramCode
# Using Scraper or API
data = await client.get_class_routine(
program_code=ProgramCode.CSE_Day,
intake="50",
section="1",
)
Output:
[ClassPeriod(week_day=<Weekday.SUNDAY: 'sun'>, period_time='08:00 AM to 09:15 AM', intake='50', section='1', faculty_code='WMO', faculty_name=None, building='2', room='416', course_code='CSE 320', course_name=None, shift_time=<ShiftTime.DAY: 'Day'>),
...
...
...
ClassPeriod(week_day=<Weekday.THURSDAY: 'thurs'>, period_time='05:15 PM to 06:30 PM', intake='50', section='1', faculty_code='SAM', faculty_name=None, building='2', room='709', course_code='CSE 351', course_name=None, shift_time=<ShiftTime.DAY: 'Day'>)]
[!NOTE]
A list of class periods containing information of each periods. Some fields likefaculty_nameare empty because theApiClientdoesn't have that information but theScraperClientdoes!
📄 Documentation
https://bubt-routinepy.readthedocs.io
🤝 Contributing
Contributions are welcome! If you'd like to improve the tool or fix bugs, feel free to submit a pull request. Please ensure your changes align with the project's coding standards and include appropriate tests.
📜 License
This project is licensed under the GPLv3 License. See the LICENSE file for full details.
By contributing to this project, you agree that your contributions will be licensed under the GPLv3 License as well.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bubt_routinepy-1.0.0.tar.gz.
File metadata
- Download URL: bubt_routinepy-1.0.0.tar.gz
- Upload date:
- Size: 134.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8807219c8fd983dd7fef1e9b4d5b33be5aeb68d813a53b819cead083a3173578
|
|
| MD5 |
dc3faaf08c21f0d4bc783e0b159c43e7
|
|
| BLAKE2b-256 |
9e007da829ab1091ef9ff7e7c0d7d76528ceb8157d0460785b14f8f5a6993db0
|
File details
Details for the file bubt_routinepy-1.0.0-py3-none-any.whl.
File metadata
- Download URL: bubt_routinepy-1.0.0-py3-none-any.whl
- Upload date:
- Size: 48.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca163c20c4b1574f37537b1d9a35874d22fa9f22472da4475c4b7517421c51e9
|
|
| MD5 |
08e724fc3c799dca54098bc419c8cbdb
|
|
| BLAKE2b-256 |
9ba88e3c4272c1e9d49a54018c3dfc28793ced6f28fc44626d1d367d61070d99
|