A Python library for fetching and parsing issues of the Bulgarian State Gazette (Държавен вестник).
Vestige gives you a clean, dependency-light Python interface to the official Държавен вестник listing. Scrape issue metadata and download links without wrestling with raw HTML or cryptic JSF form fields ever again.
- 📄 Issue Listings: Fetch paginated lists of State Gazette issues, including issue number, date, year, and type.
- 📥 Download Links: Automatically resolve the PDF and RTF download URLs for each issue.
- 🔌 Pluggable Architecture: Swap out the HTTP transport or the HTML parser via simple interfaces — great for testing with mocks.
- 🗂️ Typed Models: Clean dataclasses (
IssueEntry,DownloadFile,PageResult) withto_dict()helpers for easy JSON serialization. - ⚡ Minimal Dependencies: Only needs
selectolaxandhttpx[http2].
pip install vestige-scraperOr, to install directly from source:
pip install .import asyncio
from vestige import DVClient
async def main():
client = DVClient()
try:
# Fetch the first page of issues (with download URLs resolved)
page = await client.get_page(1)
print(page)
# PageResult(page=1, total_results=..., total_pages=..., entries=...)
for entry in page.entries:
print(entry)
for file in entry.urls:
print(f" → {file.filename}: {file.url}")
finally:
await client.aclose()
asyncio.run(main())import asyncio
from vestige import DVClient
async def main():
client = DVClient()
try:
all_pages = await client.get_all_pages(max_pages=5)
for page in all_pages:
for entry in page.entries:
print(entry.to_dict())
finally:
await client.aclose()
asyncio.run(main())page = client.get_page(1, fetch_downloads=False)| Class | Description |
|---|---|
IssueEntry |
One issue of the State Gazette — number, date, year, type, and download files. |
DownloadFile |
A single downloadable file (url, filename). |
PageResult |
One page of results — holds metadata and a list of IssueEntry objects. |
from vestige import DVClient
from vestige.network.transport import AsyncRequestsTransport
from vestige.scraping.parsers import IssueParser
client = DVClient(
transport=MyCustomTransport(),
parser=MyCustomParser(),
)Both transport and parser accept any object that satisfies the AsyncPageFetcher and PageParser interfaces defined in vestige.core.interfaces.
- Python 3.10+
asyncio>=4.0.0selectolax>=0.4.7httpx[http2]>=0.28.1
Issues and pull requests are welcome! Please file an issue if you encounter any problems or have suggestions for improvements.
Built with ❤️ for Bulgaria's open data. MIT Licensed.