Loading repository data…
Loading repository data…
ahmaad-ansari / repository
ER-Watch-Scraper is a Python-based scraper that collects real-time emergency room wait times for hospitals in Ontario. By consolidating data from various sources (APIs, HTML pages, and Power BI dashboards), this tool provides a centralized, up-to-date view of ER wait times.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
ER Watch Scraper is an async web scraping system that collects real-time emergency room wait times from hospitals across Ontario. It supports multiple data sources including REST APIs, HTML pages, and Power BI dashboards, storing results in a PostgreSQL database.
asyncio and aiohttp for fast parallel scraping.aiohttp session with connection pooling for efficient requestser-watch-scraper/
├── scraper/
│ ├── __init__.py
│ ├── main.py # Entry point - orchestrates scraping and displays run summary
│ ├── aggregator.py # Concurrent execution with failure tracking
│ ├── database/
│ │ ├── __init__.py
│ │ ├── connection.py # SQLAlchemy async database connection
│ │ └── models.py # SQLAlchemy ORM models
│ ├── parsers/
│ │ ├── __init__.py
│ │ ├── base_parser.py
│ │ ├── api_parser.py # JSON/text API response parser
│ │ └── html_parser.py # BeautifulSoup HTML parser
│ ├── scrapers/
│ │ ├── __init__.py
│ │ ├── base_scraper.py # Abstract base class with common logic
│ │ ├── api_scraper.py # Async API scraper using aiohttp
│ │ ├── html_scraper.py # Async HTML scraper using aiohttp
│ │ └── pbi_scraper.py # Power BI scraper using Playwright
│ ├── repository/
│ │ ├── __init__.py
│ │ └── supabase_repository.py # Database operations (UPSERT)
│ └── utils/
│ ├── __init__.py
│ ├── logger.py # Color-coded logger with hospital context
│ ├── data_formatter.py # Value normalization (dates, times, integers)
│ ├── field_mappings.py # Centralized field name mappings
│ ├── retry.py # Async retry with exponential backoff
│ └── http_client.py # Shared aiohttp session management
├── migrations/
│ ├── env.py
│ ├── script.py.mako
│ └── versions/
│ └── 20250126_000000_initial_schema.py
├── data/ # Private - scraping target CSV files (gitignored)
├── alembic.ini
├── requirements.txt
├── .env
└── README.md
Clone the Repository
git clone https://github.com/ahmaad-ansari/er-watch-scraper.git
cd er-watch-scraper
Create a Virtual Environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
Install Dependencies
pip install -r requirements.txt
Install Playwright Browsers (for Power BI scraping)
playwright install chromium
Configure Environment Variables
Create a .env file in the project root:
DB_USER=your_db_user
DB_PASSWORD=your_db_password
DB_HOST=localhost
DB_PORT=5432
DB_NAME=your_db_name
This project uses Alembic for database schema management.
Run migrations:
alembic upgrade head
Create a new migration:
alembic revision --autogenerate -m "Description of changes"
Check current migration status:
alembic current
| Table | Purpose |
|---|---|
hospitals | Hospital information (name, address, coordinates) |
scraping_targets | Scraping configuration per hospital (URL, action, instructions) |
scraped_data | Current snapshot of ER wait times (1 row per hospital) |
scraped_data_history | Historical record of all scrapes (for analytics/trends) |
sponsors | Platform sponsor information |
The scraped_data_history table stores every scrape result, enabling:
Run the scraper:
python -m scraper.main
The script will:
After each run, a detailed summary is displayed:
============================================================
SCRAPER RUN SUMMARY
============================================================
Total hospitals: 42
Successful: 38 (90.5%)
Failed: 4 (9.5%)
FAILED HOSPITALS:
------------------------------------------------------------
Hospital ID: OHC15
Action: pbi
URL: https://app.powerbi.com/view?r=...
Error: Selector failed for 'estimatedWaitTime'
selectorSequence: [{"tag": "tspan", "nthOfType": 7}]
No element found matching selector
Hospital ID: OHT14
Action: html
URL: https://www.hospital.ca/emergency
Error: HTTP 503 Service Unavailable
============================================================
This tells you exactly:
| Variable | Description |
|---|---|
DB_USER | PostgreSQL username |
DB_PASSWORD | PostgreSQL password |
DB_HOST | Database host address |
DB_PORT | Database port (default: 5432) |
DB_NAME | Database name |
scraper/scrapers/ inheriting from BaseScraperscrape() methodaggregator.py to handle the new action typescraping_targets table with:
hospital_id: Unique identifierurl: Target URLaction: Scraper type (see below)scraping_instructions: JSON object with field extraction rules| Action | Description | Use Case |
|---|---|---|
api | Async HTTP request with aiohttp | Standard JSON/text APIs |
api_h | Headless browser (Playwright) + JSON parsing | APIs protected by Cloudflare/bot detection |
html | Async HTTP request + BeautifulSoup parsing | Static HTML pages |
pbi | Headless browser + HTML parsing | Power BI dashboards |
pbi_h | Headless browser with headers + HTML parsing | Protected dynamic pages |
{
"lastUpdated": {
"unit": "EST",
"pattern": "(regex pattern)",
"formatCode": "%Y-%m-%d %H:%M:%S",
"dataPath": "path.to.field", // For API
"selectorSequence": [{"tag": "div"}] // For HTML
},
"patientsWaiting": {
"dataPath": "patients.waiting"
},
"estimatedWaitTime": {
"unit": "minutes",
"pattern": "(\\d+)",
"dataPath": "wait.time"
}
}
This project does not currently specify a license. For more information or if you wish to use this in a commercial or open-source context, please contact the repository owner.
Thank you for using ER Watch! If you encounter any issues or have suggestions, please open an issue or submit a pull request.