-
Notifications
You must be signed in to change notification settings - Fork 19
/
clarity_parser.py
146 lines (136 loc) · 5.83 KB
/
clarity_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import clarify
import requests
import zipfile
import csv
try:
from StringIO import StringIO
except ImportError:
from io import StringIO, BytesIO
def statewide_results(url):
j = clarify.Jurisdiction(url=url, level="state")
r = requests.get("http://results.enr.clarityelections.com/WV/74487/207685/reports/detailxml.zip", stream=True)
z = zipfile.ZipFile(BytesIO(r.content))
z.extractall()
p = clarify.Parser()
p.parse("detail.xml")
results = []
for result in p.results:
candidate = result.choice.text
office, district = parse_office(result.contest.text)
party = result.contest.party
if '(' in candidate and party is None:
if '(I)' in candidate:
if '(I)(I)' in candidate:
candidate = candidate.split('(I)')[0]
party = 'I'
else:
candidate, party = candidate.split('(I)')
candidate = candidate.strip() + ' (I)'
else:
print(candidate)
candidate, party = candidate.split('(', 1)
candidate = candidate.strip()
party = party.replace(')','').strip()
if result.jurisdiction:
county = result.jurisdiction.name
else:
county = None
r = [x for x in results if x['county'] == county and x['office'] == office and x['district'] == district and x['party'] == party and x['candidate'] == candidate]
if r:
r[0][result.vote_type] = result.votes
else:
results.append({ 'county': county, 'office': office, 'district': district, 'party': party, 'candidate': candidate, result.vote_type: result.votes})
with open("20181106__sc__general.csv", "wt") as csvfile:
w = csv.writer(csvfile)
w.writerow(['county', 'office', 'district', 'party', 'candidate', 'votes'])
for row in results:
total_votes = row['Election Day']# + row['Absentee by Mail'] + row['Advance in Person'] + row['Provisional']
w.writerow([row['county'], row['office'], row['district'], row['party'], row['candidate'], total_votes])
def download_county_files(url, filename):
no_xml = []
j = clarify.Jurisdiction(url=url, level="state")
subs = j.get_subjurisdictions()
for sub in subs:
try:
r = requests.get(sub.report_url('xml'), stream=True, headers={"User-Agent": "Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion"})
z = zipfile.ZipFile(BytesIO(r.content))
z.extractall()
precinct_results(sub.name.replace(' ','_').lower(),filename)
except:
no_xml.append(sub.name)
print(no_xml)
def precinct_results(county_name, filename):
f = filename + '__' + county_name + '__precinct.csv'
p = clarify.Parser()
p.parse("detail.xml")
results = []
vote_types = []
for result in [x for x in p.results if not 'Number of Precincts' in x.vote_type]:
vote_types.append(result.vote_type)
if result.choice is None:
continue
candidate = result.choice.text
office, district = parse_office(result.contest.text)
party = result.choice.party
if '(' in candidate and party is None:
if '(I)' in candidate:
if '(I)(I)' in candidate:
candidate = candidate.split('(I)')[0]
party = 'I'
else:
candidate, party = candidate.split('(I)')
else:
candidate, party = candidate.split('(', 1)
candidate = candidate.strip()
party = party.replace(')','').strip()
county = p.region
if result.jurisdiction:
precinct = result.jurisdiction.name
else:
precinct = None
if precinct == None:
continue
r = [x for x in results if x['county'] == county and x['precinct'] == precinct and x['office'] == office and x['district'] == district and x['party'] == party and x['candidate'] == candidate]
if r:
r[0][result.vote_type] = result.votes
else:
results.append({ 'county': county, 'precinct': precinct, 'office': office, 'district': district, 'party': party, 'candidate': candidate, result.vote_type: result.votes})
vote_types = list(set(vote_types))
if 'Overvotes' in vote_types:
vote_types.remove('Overvotes')
if 'Undervotes' in vote_types:
vote_types.remove('Undervotes')
with open(f, "wt") as csvfile:
w = csv.writer(csvfile)
headers = ['county', 'precinct', 'office', 'district', 'party', 'candidate', 'votes'] + [x.replace(' ','_').lower() for x in vote_types]
w.writerow(headers)
for row in results:
if 'Republican' in row['office']:
row['party'] = 'REP'
elif 'Democrat' in row['office']:
row['party'] = 'DEM'
total_votes = sum([row[k] for k in vote_types if row[k]])
w.writerow([row['county'], row['precinct'], row['office'], row['district'], row['party'], row['candidate'], total_votes] + [row[k] for k in vote_types])
def parse_office(office_text):
if ' - ' in office_text:
office = office_text.split('-')[0]
else:
office = office_text.split(',')[0]
if ', District' in office_text:
district = office_text.split(', District')[1].split(' - ')[0].strip()
elif 'United States Senator' in office_text:
office = 'United States Senator'
district = None
elif ',' in office_text:
district = office_text.split(',')[1]
else:
district = None
return [office.strip(), district]
def parse_party(office_text):
if '- REP' in office_text:
party = 'REP'
elif '- DEM' in office_text:
party = 'DEM'
else:
party = None
return party