| name | brightspace-scraper |
| description | Scrape course materials from Brightspace LMS. Use when (1) need to download course content (slides, labs, assignments), (2) organize course materials locally, (3) filter specific module types, (4) batch download from multiple courses. |
Brightspace Course Scraper
Objectives
- Automate downloading of course materials from Brightspace LMS
- Organize content by course and module hierarchy
- Filter specific content types (slides, labs, assignments, etc.)
- Handle authentication and session management
- Avoid re-downloading unchanged content
Script Location
.skills/learning-brightspace_scraper/scripts/brightspace/scraper.py
Quick Start
1. First Time Setup - Login
cd .skills/learning-brightspace_scraper/scripts
uv run python run.py --login-only
This opens a browser for manual login. Session is saved to .session.json for future use.
2. List Available Courses
uv run python run.py --list-courses
Shows all enrolled courses with their IDs.
3. Scrape Entire Course
uv run python run.py --course 846088
4. Scrape Specific Module Type
uv run python run.py --course 846088 --module slides
uv run python run.py --course 846088 --module labs
uv run python run.py --course 846088 --module assignment
uv run python run.py --course 846088 --module "Week 1"
Configuration
Edit .skills/learning-brightspace_scraper/scripts/brightspace/config.py:
COURSES = {
"846088": "ml",
"846083": "nlp",
"846092": "mv",
"846085": "rl",
}
OUTPUT_DIR = Path(__file__).parent / "data"
Command Line Options
| Option | Short | Description |
|---|
--course | -c | Course ID to scrape |
--module | -m | Filter modules by name (partial match) |
--headless | | Run browser in headless mode |
--login-only | | Only perform login and save session |
--list-courses | -l | List all available courses |
--keep-open | -k | Keep browser open after completion |
--dump-html | | Save page HTML for debugging |
How It Works
1. Authentication
- Uses Playwright to automate browser
- Saves session cookies to
.session.json
- Reuses session for subsequent runs
- Manual login required only once
2. Content Discovery
- Navigates course content tree structure
- Parses module hierarchy (parent/child relationships)
- Identifies content types (PDF, PPTX, links, HTML pages)
- Tracks content with unique IDs
3. Smart Downloading
- Computes content hash to detect changes
- Skips unchanged files (stored in
.content_hashes.json)
- Downloads files via "Download" button clicks
- Extracts external links to
links.md
- Saves HTML snapshots for reference
4. Module Filtering
When --module is specified:
- Case-insensitive partial matching
- Matches module title or full path
- Automatically enters parent modules if children match
- Example:
--module slides matches "Slides", "Week 1 Slides", "Course Slides"
5. Content Organization
data/ # Root data directory
โโโ ml/ # Course directory
โโโ .content_hashes.json # Change detection
โโโ index.html # Course home page
โโโ Week 1/ # Module
โ โโโ index.html
โ โโโ Slides/ # Sub-module
โ โ โโโ index.html
โ โ โโโ 12345_Lecture1.pdf
โ โ โโโ links.md
โ โโโ Labs/
โ โโโ index.html
โ โโโ 67890_Lab1.pdf
โโโ Week 2/
โโโ ...
Common Workflows
Workflow 1: Download All Course Materials
cd .skills/learning-brightspace_scraper/scripts
uv run python run.py --login-only
uv run python run.py
Workflow 2: Update Specific Content Type
uv run python run.py --course 846088 --module slides
uv run python run.py --course 846088 --module labs
Workflow 3: Download Single Week
uv run python run.py --course 846088 --module "Week 3"
Workflow 4: Debug Scraping Issues
uv run python run.py --course 846088 --keep-open
uv run python run.py --course 846088 --dump-html
Validation
After scraping, verify:
Troubleshooting
Session Expired
Symptom: Redirected to login page
Solution:
cd .skills/learning-brightspace_scraper/scripts/brightspace
rm .session.json
cd ../..
uv run python run.py --login-only
Missing Content
Symptom: Expected files not downloaded
Solution:
- Check if content is in sub-module (use
--keep-open to inspect)
- Verify module filter isn't too restrictive
- Check HTML snapshots for content structure
Download Button Not Found
Symptom: "No download button found" message
Solution:
- Content might be embedded (check HTML snapshot)
- Try without
--headless to see browser behavior
- File might be in iframe or require special handling
Rate Limiting
Symptom: Slow downloads or timeouts
Solution:
- Script includes random delays (1-3 seconds)
- Adjust
MIN_DELAY and MAX_DELAY in script if needed
Integration with Course Organization
After scraping, move content to course directories:
Copy-Item -Recurse data/ml/Week\ 1/Slides/*.pdf courses/ml/slides/
Best Practices
- Login once per session - Session persists across runs
- Use module filters - Faster and more targeted
- Run incrementally - Only new/changed content is downloaded
- Check HTML snapshots - Useful for debugging structure
- Keep browser open for debugging - Use
--keep-open when troubleshooting
- Organize after scraping - Move from
data/ to courses/ structure
Dependencies
uv add playwright
uv run playwright install chromium
Advanced Usage
Custom Course Mapping
Add new courses to config.py:
COURSES = {
"123456": "new-course",
}
Modify Content Detection
Edit _process_item() method to handle new file types:
file_types = ["pdf", "ppt", "pptx", "doc", "docx", "ipynb", "py"]
Change Output Directory
Edit config.py:
OUTPUT_DIR = Path("/custom/path/to/output")
For implementation details: See scripts/brightspace/scraper.py source code