Skip to content

Instantly share code, notes, and snippets.

@zellux
Created February 14, 2026 18:09
Show Gist options
  • Select an option

  • Save zellux/cba602c7fa6a8b26e23bb0f9b299a8e5 to your computer and use it in GitHub Desktop.

Select an option

Save zellux/cba602c7fa6a8b26e23bb0f9b299a8e5 to your computer and use it in GitHub Desktop.
Fetch San Mateo County Library preschooler events
#!/usr/bin/env python3
"""
Fetch San Mateo County Library events for preschoolers from the next 3 days.
Scrapes https://smcl.bibliocommons.com/v2/events with audience filter
for "Preschoolers (0-5 years old)" and a 3-day date window starting today.
"""
import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
BASE_URL = "https://smcl.bibliocommons.com/v2/events"
PRESCHOOLER_AUDIENCE_ID = "564274cf4d0090f742000011"
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
)
}
def fetch_events(days=3):
today = datetime.now()
end = today + timedelta(days=days - 1)
params = {
"audiences": PRESCHOOLER_AUDIENCE_ID,
"startDate": today.strftime("%Y-%m-%d"),
"endDate": end.strftime("%Y-%m-%d"),
}
resp = requests.get(BASE_URL, params=params, headers=HEADERS, timeout=30)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
items = soup.find_all(class_="cp-events-search-item")
events = []
for item in items:
# Title
title_tag = item.find(class_="cp-event-title")
title = title_tag.get_text(strip=True) if title_tag else "N/A"
# Link
link_tag = item.find("a", attrs={"data-key": "event-link"})
link = link_tag["href"] if link_tag else ""
# Date & time — use the screen-reader spans within cp-event-date-time
date_time_span = item.find(class_="cp-event-date-time")
if date_time_span:
sr_spans = date_time_span.find_all(class_="cp-screen-reader-message")
date_str = sr_spans[0].get_text(strip=True) if len(sr_spans) > 0 else ""
time_str = sr_spans[1].get_text(strip=True) if len(sr_spans) > 1 else ""
date_time = f"{date_str}, {time_str}" if date_str and time_str else date_str or time_str
else:
date_time = ""
# Location — use the screen-reader span to get clean (non-duplicated) text
location_tag = item.find(class_="cp-event-location-name")
if location_tag:
loc_sr = location_tag.find(class_="cp-screen-reader-message")
if loc_sr:
location = loc_sr.get_text(strip=True).replace("Event location: ", "")
else:
location = location_tag.get_text(strip=True)
else:
location = "N/A"
# Description
desc_tag = item.find(class_="cp-event-description")
description = desc_tag.get_text(strip=True) if desc_tag else ""
events.append({
"title": title,
"date_time": date_time,
"location": location,
"description": description,
"link": link,
})
return events, today, end
def main():
events, start, end = fetch_events()
print(f"San Mateo County Library — Preschooler Events")
print(f"{start.strftime('%A, %B %d')} through {end.strftime('%A, %B %d, %Y')}")
print(f"{'=' * 70}")
if not events:
print("No events found for this date range.")
return
for i, evt in enumerate(events, 1):
print(f"\n{i}. {evt['title']}")
print(f" When: {evt['date_time']}")
print(f" Where: {evt['location']}")
if evt["description"]:
# Wrap long descriptions
desc = evt["description"]
if len(desc) > 120:
desc = desc[:117] + "..."
print(f" About: {desc}")
print(f" Link: {evt['link']}")
print(f"\n{'=' * 70}")
print(f"Total: {len(events)} events")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment