Search by

yannxtrem / grsu-timetable

yannXtrem

PHP scraper for student group timetables from Yanka Kupala State University of Grodno (GRSU) - raspisanie.grsu.by

Package info

github.com/yannXtrem/grsu-timetable

pkg:composer/yannxtrem/grsu-timetable

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-16 13:47 UTC

This package is auto-updated.

Last update: 2026-09-16 13:53:28 UTC


README

A PHP scraper library for fetching and parsing student group class schedules from the Yanka Kupala State University of Grodno (GRSU) online timetable at raspisanie.grsu.by.

Features

  • Scrapes weekly schedules from the GRSU timetable portal
  • Parses weekday, date, time, discipline, lecturer, subgroup, and classroom data
  • Built-in in-memory cache with configurable TTL
  • Drop-in Laravel cache adapter via service provider
  • toArray() output format compatible with the existing Python/Flask API
  • Supports both plain PHP and Laravel integration

Requirements

  • PHP ^8.1
  • GuzzleHttp ^7.0
  • Symfony DomCrawler + CSS Selector ^6.0 | ^7.0

Installation

composer require yannxtrem/grsu-timetable

Laravel auto-discovery registers the service provider automatically.

Quick Start

Plain PHP

use Yannxtrem\GrsuTimetable\GrsuTimetable;

$timetable = new GrsuTimetable();

// Fetch schedule for a specific date
$week = $timetable->forDate('2026-04-22');

if ($week !== null) {
    echo "Group: " . $week->groupName . "\n";
    echo "Week: " . $week->weekNumber . "\n";

    foreach ($week->days as $day) {
        echo "Day: " . $day->weekday . " / " . $day->monthday . "\n";
        foreach ($day->classes as $class) {
            echo "  " . $class->time->start->format('H:i') . " - " . $class->time->end->format('H:i');
            echo "  " . $class->subject->name;
            echo "  (" . $class->subgroup . ")";
            if ($class->door !== null) {
                echo "  Room: " . $class->door;
            }
            echo "\n";
        }
    }
}

Laravel

The package auto-registers via extra.laravel.providers in composer.json. You can publish the config:

php artisan vendor:publish --tag=grsu-timetable-config

Resolve via dependency injection or the alias:

use Yannxtrem\GrsuTimetable\GrsuTimetable;

// Via DI
$week = app(GrsuTimetable::class)->forDate(now());

// Via alias
$week = app('grsu-timetable')->forDate(now(), ['arg0' => '12345']);

Usage

forDate()

Fetches the weekly schedule containing the given date. This is the primary entry point.

$week = $timetable->forDate('2026-04-22');

// With a DateTime object
$week = $timetable->forDate(new DateTimeImmutable('2026-04-22'));

// Override group parameters
$week = $timetable->forDate('2026-04-22', [
    'arg0' => '12345',
    'arg1' => '3',
    'arg2' => '2',
    'arg3' => '1',
    'arg4' => '1',
]);

// Force refresh (bypass cache)
$week = $timetable->forDate('2026-04-22', forceRefresh: true);

// Skip scraping if not cached
$week = $timetable->forDate('2026-04-22', scrapeIfMissing: false);

Parameters:

Name Type Default Description
$date DateTimeInterface|string required Date in Y-m-d format or a DateTime object
$groupParams array [] Override for arg0-arg4 group parameters
$forceRefresh bool false Bypass cache and re-scrape
$scrapeIfMissing bool true Auto-scrape when not found in cache

Returns: ?ScheduleWeek

Throws: InvalidArgumentException if the date string is malformed.

getByGroup()

Retrieves a schedule by group name and week number, using cache-first lookup.

$week = $timetable->getByGroup('СДП-УИР-251', 2);

// With a known URL for scraping on cache miss
$week = $timetable->getByGroup('СДП-УИР-251', 2, url: 'https://raspisanie.grsu.by/...');

Returns null if not cached and no URL is provided.

scrapeUrl()

Scrapes a raw URL directly, bypassing cache read. The result is always stored in cache.

$week = $timetable->scrapeUrl('https://raspisanie.grsu.by/TimeTable/PrintPage.aspx?arg0=18156&...');

Cache Management

// List all cached URLs
$urls = $timetable->cachedUrls();

// Clear all managed cache entries
$timetable->clearCache();

// Swap the cache store at runtime
use Yannxtrem\GrsuTimetable\Cache\LaravelCacheStore;
$timetable->setCache(new LaravelCacheStore($laravelCache));

Configuration

Publish the config file in Laravel:

php artisan vendor:publish --tag=grsu-timetable-config

This creates config/grsu-timetable.php:

return [
    // Default group identifiers for raspisanie.grsu.by
    'default_group_params' => [
        'arg0' => '18156',  // Main group ID
        'arg1' => '3',
        'arg2' => '2',      // Week number
        'arg3' => '1',
        'arg4' => '1',
    ],

    // Cache TTL in seconds (default: 1 hour)
    'cache_ttl' => 3600,

    'cache' => [
        'enabled' => true,   // false = use the package's in-memory cache
        'store' => null,     // null = Laravel's default cache store
    ],
];

Data Models

All models implement toArray() for serialization and fromArray() for deserialization.

ScheduleWeek

Property Type Description
$weekNumber int Week number on the timetable
$groupName string Student group name
$days ScheduleDay[] Array of days in the week

ScheduleDay

Property Type Description
$weekday int Day of week (0 = Monday, 6 = Sunday)
$monthday int Day of month
$classes ScheduleClass[] Classes scheduled for this day

ScheduleClass

Property Type Description
$subject Subject The discipline being taught
$time ScheduleTime Start and end times
$subgroup string Subgroup name ("Tous" if none)
$door ?string Classroom/auditorium (null if not specified)

ScheduleTime

Property Type Description
$start DateTimeImmutable Class start time
$end DateTimeImmutable Class end time

Subject

Property Type Description
$name string Discipline name
$lecturer Lecturer Assigned lecturer

Lecturer

Property Type Description
$name string Lecturer name

Array Output Format

The toArray() method produces a structure matching the existing Python/Flask API:

{
    "week_number": 2,
    "group_name": "СДП-УИР-251",
    "days": [
        {
            "weekday": 0,
            "monthday": 20,
            "classes": [
                {
                    "subject": {
                        "name": "Математический анализ",
                        "lecturer": {
                            "name": "Иванов И.И."
                        }
                    },
                    "time": {
                        "start": "09:40",
                        "end": "11:05"
                    },
                    "subgroup": "1",
                    "door": "ауд. 212"
                }
            ]
        }
    ]
}

Cache

The package ships with two cache implementations:

Store Description
ArrayCacheStore In-memory cache with TTL (default)
LaravelCacheStore Wraps Laravel's Cache::store()

In Laravel, the service provider automatically uses LaravelCacheStore when cache.enabled is true in the config.

Testing

vendor/bin/phpunit

Tests use Guzzle MockHandler against a local HTML fixture -- no network requests are made.

License

MIT