No description
  • HTML 96.6%
  • Python 3%
  • Typst 0.3%
Find a file
2026-06-24 15:21:53 +02:00
abstracts_clean Update room assignments and refresh scraped content 2026-06-05 10:54:09 +02:00
abstracts_pdf Update room assignments and refresh scraped content 2026-06-05 10:54:09 +02:00
sessions Update room assignments and refresh scraped content 2026-06-05 10:54:09 +02:00
tessdata_best SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
.gitignore SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
abs_urls.txt Update room assignments and refresh scraped content 2026-06-05 10:54:09 +02:00
bli bli 2026-06-24 15:21:53 +02:00
broken_abstracts.json SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
data.json Fix one-day shift of 10h45 plenary talks (rowspan-aware S00 parsing) 2026-06-16 07:57:16 +02:00
extract.py SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
fetch_abstracts.sh SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
fetch_pages.sh SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
gen.py SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
index.html Fix one-day shift of 10h45 plenary talks (rowspan-aware S00 parsing) 2026-06-16 07:57:16 +02:00
parse.py Fix one-day shift of 10h45 plenary talks (rowspan-aware S00 parsing) 2026-06-16 07:57:16 +02:00
pre-common.typ SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
pre-programme.typ SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
programme.md Fix one-day shift of 10h45 plenary talks (rowspan-aware S00 parsing) 2026-06-16 07:57:16 +02:00
programme.pdf Fix one-day shift of 10h45 plenary talks (rowspan-aware S00 parsing) 2026-06-16 07:57:16 +02:00
programme.qmd Fix one-day shift of 10h45 plenary talks (rowspan-aware S00 parsing) 2026-06-16 07:57:16 +02:00
programme_raw.html Update room assignments and refresh scraped content 2026-06-05 10:54:09 +02:00
README.md SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
requirements.txt SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00
typst-template.typ SF2A 2026 programme: scraper, abstract extraction, and generated outputs 2026-06-04 12:52:14 +02:00

SF2A 2026 — Programme unifié

Pipeline that scrapes the SF2A 2026 conference (Journées de la SF2A, 2226 June 2026, Grenoble) programme and all session pages, extracts the abstracts from the official PDFs, and regenerates the whole programme as:

  • index.html — standalone webpage: chronological calendar grid, afternoon parallel sessions side by side per amphitheatre, collapsible abstracts. No external assets; just open it in a browser or drop it on any web server.
  • programme.pdf — full programme with abstracts, typeset via Quarto/Typst (linked from the webpage header).
  • programme.md — same content as plain Markdown.

Everything is regenerable from the SF2A website with the steps below; the intermediate data files are committed so the outputs can also be rebuilt offline from stage 4 onward.

Pipeline

Stage Command Reads Writes
1. Fetch pages ./fetch_pages.sh journees.sf2a.eu programme_raw.html, sessions/s00s21.html
2. Parse ./parse.py stage 1 output data.json, abs_urls.txt
3. Fetch abstracts ./fetch_abstracts.sh abs_urls.txt abstracts_pdf/*.pdf (191 files)
4. Extract text ./extract.py abstracts_pdf/, tessdata_best/ abstracts_clean/*.txt, broken_abstracts.json
5. Generate ./gen.py data.json, abstracts_clean/ index.html, programme.md, programme.qmd
6. Render PDF quarto render programme.qmd programme.qmd, *.typ programme.pdf

To reproduce just the webpage, stages 5 alone (./gen.py) is enough — all of its inputs are in the repo. Run the full chain only to pick up changes from the SF2A site.

Dependencies

  • Python 3 with PyMuPDF (pip install -r requirements.txt) — tested with PyMuPDF 1.27
  • poppler-utils (pdftoppm) — rasterises PDFs for OCR
  • tesseract-ocr ≥ 5 — OCR fallback (language packs not needed; the models ship in tessdata_best/, see below)
  • curl — stages 1 and 3
  • Quarto ≥ 1.4 (bundles Typst) — stage 6 only

On Debian/Ubuntu:

sudo apt install poppler-utils tesseract-ocr curl
pip install -r requirements.txt
# Quarto: https://quarto.org/docs/get-started/

How the abstract text is obtained (extract.py)

The goal is the exact published text, so OCR is the last resort:

  1. Direct extraction (186 of 191 PDFs): the embedded text layer is read in layout order with PyMuPDF, then TeX-style decomposed accents (standalone accent glyph before the base letter, e.g. ´e) are recombined into proper composed characters (é).
  2. OCR fallback (4 PDFs): three PDFs have a broken ligature ToUnicode map (direct extraction yields garbage) and one has no text layer at all. These are rasterised at 400 dpi and OCRed with the Tesseract best models, French + English. The models in tessdata_best/ come from tesseract-ocr/tessdata_best (Apache 2.0) and are committed so results are reproducible bit-for-bit.
  3. Broken links (1 PDF): one abstract URL returns an HTML error page; it is recorded in broken_abstracts.json and shown as "résumé non disponible".

All texts are then reflowed (hard line breaks collapsed, hyphenation at line ends undone) and, in gen.py, the title/author/affiliation preamble and page footers are stripped heuristically so only the abstract body is displayed.

Repository layout

fetch_pages.sh        stage 1 — download programme + session pages
parse.py              stage 2 — HTML → data.json (+ abstract URL list)
fetch_abstracts.sh    stage 3 — download abstract PDFs
extract.py            stage 4 — PDFs → clean abstract text
gen.py                stage 5 — data.json + abstracts → html/md/qmd
typst-template.typ    ┐
pre-common.typ        ├ Typst styling for the PDF (stage 6)
pre-programme.typ     ┘
tessdata_best/        Tesseract 'best' models (fra+eng), for OCR fallback
programme_raw.html    ┐
sessions/             ├ scraped inputs (stages 1, 3) — committed for
abstracts_pdf/        ┘ offline reproducibility
data.json             ┐
abs_urls.txt          ├ intermediates (stages 2, 4)
abstracts_clean/      │
broken_abstracts.json ┘
index.html            ┐
programme.md          ├ final outputs (stages 5, 6)
programme.qmd         │
programme.pdf         ┘

Notes & caveats

  • Fonts (PDF only): programme.qmd and the .typ files reference the licensed "ABC … Edu" font families plus Roboto. If they are not installed, Typst prints "unknown font family" warnings and falls back to its bundled default fonts — the render still succeeds, only the typefaces differ. Edit the mainfont line in gen.py and the fonts in pre-common.typ / pre-programme.typ to use your own.
  • The afternoon room grid (AFTERNOON in parse.py), evening events and morning notes were transcribed by hand from the published programme grid; if the SF2A reshuffles rooms, update those tables.
  • Two session pages use header-less tables with their own column layouts; parse.py handles them specially (parse_headerless).
  • Times are normalised to 24-hour HH:MM; bare hours below 8 are assumed to be afternoon (the earliest session starts at 09:00).
  • The scraped pages and abstracts are © their authors / the SF2A; this repo redistributes them solely so the conference programme can be rebuilt.