Lightweight tool for querying Online Judge statistics across multiple platforms
Project description
OJHunt Lite
A lightweight async Python tool for querying Online Judge (OJ) statistics across multiple platforms. Track your accepted problems and total submissions from competitive programming sites.
- Async/concurrent requests via
aiohttp - CLI and web interface
- BSD-2 Licensed
CLI
Install once, use anywhere (pipx, uv tool, or pip):
pipx install ojhunt
# or: uv tool install ojhunt
# or: pip install ojhunt
Run directly from a clone (no install needed):
git clone https://github.com/Liu233w/ojhunt-lite
cd ojhunt-lite
uv run ojhunt tourist@codeforces
Run via container (no Python needed):
docker run --rm ghcr.io/liu233w/ojhunt-lite tourist@codeforces
Example output:
$ ojhunt tourist@codeforces tourist@atcoder
Querying CodeForces...
Querying AtCoder...
AtCoder done (1051 solved, 1.25s)
CodeForces done (2962 solved, 2.78s)
Total: 2962 solved / 6437 submissions
┏━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Crawler ┃ Username ┃ Solved ┃ Submissions ┃ Status ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ CodeForces │ tourist │ 2962 │ 5386 │ OK (2.78s) │
│ AtCoder │ tourist │ 1051 │ 1051 │ OK (1.25s) │
└────────────┴──────────┴────────┴─────────────┴────────────┘
Completed: 2 OK, 0 failed (2.78s total)
Full CLI reference, login-required crawlers, and JSON output: docs/cli.md
Web Interface
The web interface is designed to be self-hosted. Clone the repo and deploy:
git clone https://github.com/Liu233w/ojhunt-lite
cd ojhunt-lite
uv sync
uv run fastapi run src/ojhunt/web/app.py --port 8080
Container images are available at ghcr.io/liu233w/ojhunt-lite — see docs/web.md.
Use Crawlers in Your Code
Add ojhunt as a project dependency:
uv add ojhunt
# or: pip install ojhunt
Sync (simplest):
from ojhunt.crawlers.codeforces import query
from ojhunt.crawlers import query_sync
result = query_sync(query, "tourist")
print(result.solved, result.submissions, result.solved_list)
Async (when you already have an event loop):
import asyncio, aiohttp
from ojhunt.crawlers.codeforces import query
from ojhunt.crawlers import CrawlerResult
async def main():
async with aiohttp.ClientSession() as session:
result = CrawlerResult.from_dict(await query(session, "tourist"))
print(result.solved, result.submissions, result.solved_list)
asyncio.run(main())
query_sync and CrawlerResult work with any crawler in ojhunt.crawlers.*.
Some crawlers (nit, uva) use a persistent label cache and require the full package — they cannot be used as standalone copied files.
Supported Platforms
See the src/ojhunt/crawlers/ directory. Archived crawlers (dead sites) are in archived_crawlers/.
Development
Adding crawlers, running tests, templates: docs/development.md
License
BSD 2-Clause License — see individual crawler files for full license text.
Credits
Lightweight Python rewrite of OJHunt (acm-statistics), originally inspired by 西北工业大学ACM查询系统 (npuacm.info) by Jiduo Zhang.
Special thanks to test account providers: @leoloveacm, @2013300262
Contributors ✨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
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 ojhunt-2026.5.5.33830.tar.gz.
File metadata
- Download URL: ojhunt-2026.5.5.33830.tar.gz
- Upload date:
- Size: 2.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d93fe10e90394ded339720985713b64bcecf880cf7dcbfcc26dd9b763d9cdf1
|
|
| MD5 |
09f0f3191aa16b8d29fc6f78205bea4c
|
|
| BLAKE2b-256 |
52409bc22be1c4be12e8c2f900ffb21b80e9efa59b96d2923b2dc984c3a98729
|
Provenance
The following attestation bundles were made for ojhunt-2026.5.5.33830.tar.gz:
Publisher:
release.yml on Liu233w/ojhunt-lite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ojhunt-2026.5.5.33830.tar.gz -
Subject digest:
6d93fe10e90394ded339720985713b64bcecf880cf7dcbfcc26dd9b763d9cdf1 - Sigstore transparency entry: 1439096272
- Sigstore integration time:
-
Permalink:
Liu233w/ojhunt-lite@b9ef60db263d8a949ce842c5dcc0b9f082cb3c98 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Liu233w
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b9ef60db263d8a949ce842c5dcc0b9f082cb3c98 -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file ojhunt-2026.5.5.33830-py3-none-any.whl.
File metadata
- Download URL: ojhunt-2026.5.5.33830-py3-none-any.whl
- Upload date:
- Size: 626.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e553eed4377f6dc3bad3a77628c927157b44b70b69359e06d9ba8aca90b4f164
|
|
| MD5 |
41fb6c6d6d1aae7fda8de235f54ba86f
|
|
| BLAKE2b-256 |
981746c03c6948963e006006c923221362eeaa8802a51e50f637e7b5adda0322
|
Provenance
The following attestation bundles were made for ojhunt-2026.5.5.33830-py3-none-any.whl:
Publisher:
release.yml on Liu233w/ojhunt-lite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ojhunt-2026.5.5.33830-py3-none-any.whl -
Subject digest:
e553eed4377f6dc3bad3a77628c927157b44b70b69359e06d9ba8aca90b4f164 - Sigstore transparency entry: 1439096284
- Sigstore integration time:
-
Permalink:
Liu233w/ojhunt-lite@b9ef60db263d8a949ce842c5dcc0b9f082cb3c98 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Liu233w
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b9ef60db263d8a949ce842c5dcc0b9f082cb3c98 -
Trigger Event:
workflow_run
-
Statement type: