Fetches postdoc and academic job postings (research associate, fellowship positions) from multiple RSS feeds and web sources, scores them for relevance with an LLM, and summarises the requirements.
fetch() β pulls from RSS feeds (jobs.ac.uk) + scraped pages (FindAPostDoc,
AcademicPositions, EURAXESS) β keyword filter β deduplication
process() β LLM relevance scoring β drops jobs below threshold
β LLM requirements summarisation
render() β wraps in FeedSection
config/sources.yaml β toggle only:
| Key | Default | Notes |
|---|---|---|
enabled |
false |
Set to true to activate |
config/extensions/postdoc_jobs.yaml β all other settings (see postdoc_jobs.yaml.example to restore defaults):
| Key | Default | Notes |
|---|---|---|
rss_sources |
[] |
List of {url, name} RSS feed dicts |
jina_sources |
[] |
List of {url, name, type} scraped sources |
filter_keywords |
[] |
At least one must match title or description |
exclude_keywords |
[] |
Jobs matching any of these are dropped |
llm_score_threshold |
7 |
Jobs scoring below this (0β10) are dropped |
request_timeout |
20.0 |
Seconds for job detail HTTP fetches |
jina_timeout |
30.0 |
Seconds for Jina.ai scrape requests |
{
"title": str,
"url": str,
"institution": str,
"location": str,
"deadline": str,
"salary": str,
"source": str, # e.g. "jobs.ac.uk Research"
"relevance_score": float, # LLM score 0β10
"requirements": str, # LLM-summarised requirements
}collectors/jobs_collector.pyfetch_jobs(rss_sources, filter_keywords, exclude_keywords, jina_sources)- Supports: jobs.ac.uk (RSS), FindAPostDoc, AcademicPositions, EURAXESS
- Set
postdoc_jobs.enabled: trueinconfig/sources.yaml - Edit
config/extensions/postdoc_jobs.yamlto configure sources and filters - Add it to
REGISTRYinextensions/__init__.py:from extensions.postdoc_jobs import PostdocJobsExtension REGISTRY = [..., PostdocJobsExtension]
- Update
run_daily()inmain.pyto passsections["postdoc_jobs"].itemstobuild_daily_payload()
PYTHONPATH=. pytest tests/test_jobs_collector.py -v