cjwatson: (Default)
[personal profile] cjwatson
I'm very lazy. Rather than having to keep track of Cambridge bin collection days manually, especially around holidays, I wrote a thing to convert it into an iCalendar file for me so that I could import it into Google Calendar. Here it is in case it's useful to anyone else:
#! /usr/bin/python3

from argparse import ArgumentParser
from datetime import datetime
import os.path
import re

from bs4 import BeautifulSoup
import dateutil.parser
from icalendar import (
    Calendar,
    Event,
    )
import requests


parser = ArgumentParser(
    description="Generate iCalendar file for Cambridge bin collection days.")
parser.add_argument(
    "id",
    help=(
        "Unique identifier for this calendar, normally your host name.  Make "
        "sure that this does not collide with any other calendars."))
parser.add_argument("address", help="Your street address in Cambridge.")
parser.add_argument("postcode", help="Your postcode.")
args = parser.parse_args()

now = datetime.now()
req = requests.get(
    "http://bins.cambridge.gov.uk/bins.php",
    params={"address": args.address, "postcode": args.postcode})
soup = BeautifulSoup(req.text)
cal = Calendar()
cal.add("prodid", "-//riva.pelham.vpn.ucam.org//bin-days//EN")
cal.add("version", "2.0")
cal.add("calscale", "GREGORIAN")
cal.add("x-wr-calname", "Bin days")
cal.add("x-wr-timezone", "Europe/London")
for div in soup.find_all("div", style=re.compile(r"^text-align:center")):
    desc = div.contents[0]
    when = dateutil.parser.parse(div.b.get_text(" ").rstrip("*"))
    while when < now:
        when = when.replace(year=when.year + 1)
    event = Event()
    event.add("uid", "bin-days/{:%Y%m%d}@{}".format(when, args.id))
    event.add("dtstart", when.date())
    event.add("summary", desc.capitalize())
    event.add("transp", "TRANSPARENT")
    cal.add_component(event)
with open(os.path.expanduser("~/public_html/bin-days.ics"), "wb") as out:
    out.write(cal.to_ical())
On Debian, this requires the python3-bs4, python3-dateutil, python3-icalendar, and python3-requests packages. You'll probably want to change the output path to somewhere that your calendar software can see (so if it's a web service such as Google Calendar then it needs to be something that corresponds to an accessible URL). The web-scraping is pretty gross, but it's the best I can do given the council's published data. Ideally this would itself be a web service that could generate calendars on demand for a given address and postcode, but like I say I'm lazy.

From:
Anonymous( )Anonymous This account has disabled anonymous posting.
OpenID( )OpenID You can comment on this post while signed in with an account from many other sites, once you have confirmed your email address. Sign in using OpenID.
User
Account name:
Password:
If you don't have an account you can create one now.
Subject:
HTML doesn't work in the subject.

Message:

 
Notice: This account is set to log the IP addresses of everyone who comments.
Links will be displayed as unclickable URLs to help prevent spam.

April 2017

S M T W T F S
      1
2345678
9101112131415
1617181920 2122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags