Project: Civic Band—scraping and searching PDF meeting minutes from hundreds of municipalities
16th November 2024
I interviewed Philip James about Civic Band, his “slowly growing collection of databases of the minutes from civic governments”. Philip demonstrated the site and talked through his pipeline for scraping and indexing meeting minutes from many different local government authorities around the USA.
We recorded this conversation as part of yesterday’s Datasette Public Office Hours session.
Civic Band
Philip was inspired to start thinking more about local government after the 2016 US election. He realised that there was a huge amount of information about decisions made by local authorities tucked away in their meeting minutes,but that information was hidden away in thousands of PDF files across many different websites.
There was this massive backlog of basically every decision that had ever been made by one of these bodies. But it was almost impossible to discover because it lives in these systems where the method of exchange is a PDF.
Philip lives in Alameda, which makes its minutes available via this portal powered by Legistar. It turns out there are a small number of vendors that provide this kind of software tool, so once you’ve written a scraper for one it’s likely to work for many others as well.
Here’s the Civic Band portal for Alameda, powered by Datasette.
It’s running the datasette-search-all plugin and has both tables configured for full-text search. Here’s a search for housing:
The technical stack
The public Civic Band sites all run using Datasette in Docker Containers—one container per municipality. They’re hosted on a single Hetzner machine.
The ingestion pipeline runs separately from the main hosting environment, using a Mac Mini on Philp’s desk at home.
OCR works by breaking each PDF up into images and then running Tesseract OCR against them directly on the Mac Mini. This processes in the order of 10,000 or less new pages of documents a day.
Philip treats PDF as a normalization target, because the pipeline is designed around documents with pages of text. In the rare event that a municipality publishes documents in another format such as .docx
he converts them to PDF before processing.
PNG images of the PDF pages are served via a CDN, and the OCRd text is written to SQLite database files—one per municipality. SQLite FTS provides full-text search.
Scale and storage
The entire project currently comes to about 265GB on disk. The PNGs of the pages use about 350GB of CDN storage.
Most of the individual SQLite databases are very small. The largest is for Maui County which is around 535MB because that county has professional stenographers taking detailed notes for every one of their meetings.
Each city adds only a few documents a week so growth is manageable even as the number of cities grows.
Future plans
We talked quite a bit about a goal to allow users to subscribe to updates that match specific search terms.
Philip has been building out a separate site called Civic Observer to address this need, which will store searches and then execute the periodically using the Datasette JSON API, with a Django app to record state to avoid sending the same alert more than once.
I’ve had a long term ambition to build some kind of saved search alerts plugin for Datasette generally, to allow users to subscribe to new results for arbitrary SQL queries. My sqlite-chronicle library is part or that effort—it uses SQLite triggers to maintain version numbers for individual rows in a table, allowing you to query just the rows that have been inserted or modified since the version number last time you ran the query.
Philip is keen to talk to anyone who is interested in using Civic Band or helping expand it to even more cities. You can find him on the Datasette Discord.
More recent articles
- Qwen2.5-Coder-32B is an LLM that can code well that runs on my Mac - 12th November 2024
- Visualizing local election results with Datasette, Observable and MapLibre GL - 9th November 2024