{"id":20234826,"url":"https://github.com/datamade/python-chicago-elections","last_synced_at":"2026-03-08T00:31:43.729Z","repository":{"id":146796698,"uuid":"111464928","full_name":"datamade/python-chicago-elections","owner":"datamade","description":"Python Scraper for Chicago Elections","archived":false,"fork":false,"pushed_at":"2024-11-06T01:50:51.000Z","size":114,"stargazers_count":4,"open_issues_count":5,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-03T13:21:23.826Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datamade.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-11-20T21:29:29.000Z","updated_at":"2024-12-25T08:28:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"a8928a84-bac2-4bc0-a2ed-f0b6492c869c","html_url":"https://github.com/datamade/python-chicago-elections","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/datamade/python-chicago-elections","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datamade%2Fpython-chicago-elections","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datamade%2Fpython-chicago-elections/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datamade%2Fpython-chicago-elections/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datamade%2Fpython-chicago-elections/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datamade","download_url":"https://codeload.github.com/datamade/python-chicago-elections/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datamade%2Fpython-chicago-elections/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30238857,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:30:53.000Z","status":"ssl_error","status_checked_at":"2026-03-08T00:30:44.061Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T08:13:19.820Z","updated_at":"2026-03-08T00:31:43.702Z","avatar_url":"https://github.com/datamade.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"chi-elections\n=============\n\n[![Build Status](https://travis-ci.org/datamade/python-chicago-elections.svg?branch=master)](https://travis-ci.org/datamade/python-chicago-elections)\n\nchi-elections is a Python package for loading and parsing election results from the [Chicago Board of Elections](http://www.chicagoelections.com/).\n\nSummary Results\n---------------\n\nThe Board of Elections provides election-night results at a racewide level.  The file lives at\n\nhttp://www.chicagoelections.com/results/ap/summary.txt\n\nbefore election day, for testing.\n\nIt lives at\n\nhttp://www.chicagoelections.com/ap/summary.txt\n\non election night.\n\n### Text layout\n\nFrom http://www.chicagoelections.com/results/ap/text_layout.txt:\n\n```\nSummary Export File Format      Length  Column Position\nContest Code                    4       1-4\nCandidate Number                3       5-7\nNum. Eligible Precincts         4       8-11\nVotes                           7       12-18\nNum. Completed precincts        4       19-22\nParty Abbreviation              3       23-25\nPolitical Subdivision Abbrev    7       26-32\nContest name                    56      33-88\nCandidate Name                  38      89-126\nPolitical subdivision name      25      127-151\nVote For                        3       152-154\n```\n\n### Gotchas\n\nPrior to election night, the test file will include all fields.  At some point on election night, the file will only contain the numeric values in the first 22 columns.\n\nThis means that you need to:\n\n* Make sure you save candidate names in some way, like a database, before election night\n* Make sure you store ballot order (Candidate Number in the text layout above) with the candidate.  You'll need to use this, in combination with Contest Code, to look up the cached candidates.\n\nAt some point at the end of election night, the results file will no longer be available at http://www.chicagoelections.com/ap/summary.txt and will be available at http://www.chicagoelections.com/results/ap/summary.txt\n.  ~~However, it will not be updated. You'll need to scrape, enter or load results in some other way if you need updates after election night.~~ As of the April 2, 2019 municipal election, the Chicago Board of Elections says it will keep summary.txt updated until all votes are counted.\n\n\n### Results client\n\nTo access the results:\n\n```python\nfrom chi_elections import SummaryClient\n\nclient = SummaryClient()\nclient.fetch()\nmayor = next(r for r in client.races if r.name == \"Mayor\")\nself.assertEqual(len(mayor.candidates), 5)\n\nrahm = next(c for c in mayor.candidates\n            if c.full_name == \"RAHM EMANUEL\")\nprint(rahm.vote_total)\n```\n\nIf you want to specify an alternate url, for example the test URL, pass it to the constructor of `SummaryClient`:\n\n```python\nclient = SummaryClient(url='http://www.chicagoelections.com/results/ap/summary.txt')\n```\n\nPrecinct Results\n----------------\n\nAfter election night, precinct-level results are published to https://chicagoelections.com/en/election-results.html.  The results are HTML files, so we have to scrape the results from HTML tables.\n\n### Results client\n\nTo access the results:\n\nfrom chi_elections import elections\n\n```python\nmuni_elections = [election for name, election in\n                  elections().items() if 'municipal' in name.lower()]\n\nfor election in muni_elections:\n    for name, race in election.races.items():\n        if 'alderman' in name.lower() or 'mayor' in name.lower():\n            for precinct, votes in race.precincts.items():\n                print(precinct, votes)\n```                \n\n### Command Line Interface\n\nTo download a CSV version of the summary file, run:\n\n    chi_elections summary \u003e results.csv\n\nTo hit the test file:\n\n    chi_elections summary --test \u003e results.csv\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatamade%2Fpython-chicago-elections","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatamade%2Fpython-chicago-elections","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatamade%2Fpython-chicago-elections/lists"}