#!/usr/bin/python import urllib2, sgmllib, re data = file('BBBData.csv', 'w') data.write('Name,Address,Area,Phone,"Join Year","Join Month"' + ',Rating\n') months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] phone_pat = re.compile(r'phone:\s+\((?P\d{3})\)\s+' + r'(?PNote: Edited for line length\d{3}-\d{4})') join_pat = re.compile(r'BBB\s+Accredited:\s+(?P ' + r'|'.join(months) + r')\s+(?P \d{4})') rating_pat = re.compile(r'Based on BBB files, this business ' + r'has a BBB Rating of ([A-F][-+]?)') class SGMLParse(sgmllib.SGMLParser): def __init__(self, verbose=False): sgmllib.SGMLParser.__init__(self, verbose) self.div_depth = 0 self.stores = [] self.inentry = False self.inname = False self.current_name = None self.inaddr = False self.current_addr = None self.current = None self.inphone = False self.current_join = None self.current_phone = None self.last_href = None self.current_rating = None def parse(self, text): self.feed(text) self.close() def start_div(self, attributes): self.div_depth += 1 classes = [ ] attr = dict(attributes) if attr.has_key('class'): classes = attr['class'].split(' ') if 'StdList' in classes: self.inentry = self.div_depth elif 'StdListName' in classes: self.inname = self.div_depth self.current = '' elif 'StdListAddr' in classes: self.inaddr = self.div_depth self.current = '' elif 'StdListPhone' in classes: self.inphone = self.div_depth self.current = '' def end_div(self): if self.inentry == self.div_depth: # Collect data and append self.stores.append({'Name': self.current_name, 'Address': self.current_addr, 'Joined': self.current_join, 'Phone': self.current_phone, 'Rating': self.current_rating }) data.write('"'+self.current_name+'",') data.write('"'+self.current_addr+'",') data.write('"'+self.current_phone[0]+'",') data.write('"'+self.current_phone[1]+'",') data.write(''+str(self.current_join[1])+',') data.write(''+str(self.current_join[0])+',') data.write('"'+str(self.current_rating)+'"\n') self.current_name = None self.current_address = None self.current_join = None self.current_phone = None self.current_rating = None self.inentry = False elif self.inname == self.div_depth: self.current_name = self.current self.current = None self.inname = False elif self.inaddr == self.div_depth: self.current_addr = self.current self.current = None self.inaddr = False elif self.inphone == self.div_depth: for line in self.current.split('\n'): match = join_pat.match(line) if match: self.current_join = (months.index(match. group('month')), int(match. group('year'))) else: match = phone_pat.match(line) if match: if self.current_phone != None: print 'Duplicate Phone Number' self.current_phone = (match. group( 'area'), match. group('num')) self.current = None self.inphone = False self.div_depth -= 1 def start_a(self, attributes): attr = dict(attributes) if self.inentry: self.last_href = 'http://dc-easternpa.bbb.org/' \ + attr['href'] self.current = '' def end_a(self): if self.inentry and self.current == 'BBB report': match = rating_pat.search(urllib2.urlopen(self. last_href).read()) if match: self.current_rating = match.group(1) self.current = None self.last_href = None def handle_data(self, data): if self.current is not None: self.current += data def start_br(self, attributes): if self.current is not None: self.current += '\n' def handle_entityref(self, entity): if entity.lower() == 'nbsp' and self.current is not \ None: self.current += ' ' return self.convert_entityref(entity) BBBListHTML = urllib2.urlopen('http://dc-easternpa.bbb.org/' + 'V2RosterByTob.asp?ID=10049') p = SGMLParse() p.parse(''.join(BBBListHTML.readlines())) data.close() # p.stores contains a list of dictionaries with each store's # data
Wednesday, November 10, 2010
Hold it there Electric Cowboy, not so fast...
Well, it looks like the Leviton Evr-Green EVSE isn't going to be available for Christmas this year after all.
They've pushed their release for the EVB22-3PM back until January with the EVB45-3PD (the 7.6kW unit, and the one I want) hopefully out by April, but no guarantees doesn't look to be available for another year, well after I theoretically take possession of my LEAF. But what Chris at Leviton explained to me with respect to the 2010 EVSE tax credit was even more distressing: simply wiring the home in 2010 would not qualify for the tax credit even if the EVSE wasn't available. Zounds! So I called my Congressman and left a message with his office to please please please do what he can to get the EVSE tax credit extended into 2011, when most J1772-compliant EVSE equipment will finally become available to the general consumer and when EVs will finally be made available to the general public. I also asked for him to confirm the wiring restriction with respect to the tax credit. Talk about catch-22: you can have the credit for an EVSE but no EVSEs will be available until that credit expires!? I repeat, Zounds!
And here I finally got my code together to scan the Better Business Bureau website for all the local Electrical Contractors with A+ ratings after a couple hours hacking last night, as can be seen in this Google Spreadsheet (Note: The month index is 0-based, meaning January is 0). The code to do this had to query every sub-page of the 276 registered contractors and thus took quite a while to run, but here's the simple Python script I used to compile my data:
Labels:
Better Business Bureau,
Congress,
Dominion Virginia Power,
EVSE,
Leviton
Subscribe to:
Post Comments (Atom)
Thanks for the update. I'm waiting on the Evr-Green EVSE to release, but it sounds like it won't be ready on time for my Nissan Leaf in January.
ReplyDelete