Source code for influenceexplorer

import urllib2
import urllib
try:
    import json
except ImportError:
    import simplejson as json
    
from transparencydata import DEFAULT_URL


# defaults of None don't mean that there is not default or no limit--
# it means that no parameter will be sent to the server, and the server
# will use its own default.
DEFAULT_LIMIT = None

DEFAULT_CYCLE = "-1" # -1 will return career totals.


[docs]class InfluenceExplorer(object): def __init__(self, api_key, base_url=DEFAULT_URL): self.base_url = base_url if base_url[-1] == '/' else base_url + '/' self.api_key = api_key self.entities = Entities(self) self.pol = Politician(self) self.indiv = Individual(self) self.org = Organization(self) def _get_url_json(self, path, cycle=None, limit=None, **params): """ Low level call that just adds the API key, retrieves the URL and parses the JSON. """ if cycle: params.update({'cycle': cycle}) if limit: params.update({'limit': limit}) params.update({'apikey': self.api_key}) fp = urllib2.urlopen(self.base_url + path + '?' + urllib.urlencode(params)) return json.loads(fp.read())
class SubAPI(object): def __init__(self, main_api): self._get_url_json = main_api._get_url_json
[docs]class Entities(SubAPI):
[docs] def search(self, query): """ Return entities with names matching the given query. Query terms are space separated. Matches must contain all terms from the query. """ return self._get_url_json('entities.json', search=query.encode('ascii', 'ignore'))
_camp_fin_markers = ['contributor_count', 'recipient_count'] _lobbying_markers = ['lobbying_count'] _spending_markers = ['grant_count', 'loan_count', 'contract_count'] _earmark_markers = ['earmark_count']
[docs] def metadata(self, entity_id): """Return all available metadata for the given entity.""" results = self._get_url_json('entities/%s.json' % entity_id) results['years'] = self._entity_years(results['totals'], self._camp_fin_markers + self._lobbying_markers + self._spending_markers) results['camp_fin_years'] = self._entity_years(results['totals'], self._camp_fin_markers) results['lobbying_years'] = self._entity_years(results['totals'], self._lobbying_markers) results['spending_years'] = self._entity_years(results['totals'], self._spending_markers) results['earmark_years'] = self._entity_years(results['totals'], self._earmark_markers) return results
def _entity_years(self, totals, keys): years = [year for (year, values) in totals.items() if any([v for (k,v) in values.items() if k in keys]) and year != "-1"] years.sort() if years: return dict(start=years[0], end=years[-1]) else: return {}
[docs] def id_lookup(self, namespace, id): """ Return the Influence Explorer entity ID based on a 3rd party ID. Valid namespaces include: urn:crp:individual -- CRP's contributor or lobbyist ID urn:crp:organization -- CRP's organization ID urn:crp:recipient -- CRP's candidate ID urn:crp:industry -- CRP's 3-letter category order urn:crp:subindustry -- CRP's 5-letter category code urn:nimsp:subindustry -- 5-letter category code added by NIMSP urn:nimsp:organization -- NIMSP's organization ID urn:nimsp:recipient -- NIMSP's candidate ID urn:sunlight:lobbyist_registration_tracker_url -- URL of Sunlight's lobbyist registration tracker page """ return self._get_url_json('entities/id_lookup.json', namespace=namespace, id=id)
[docs] def count(self, type=None): """ Return the total count of entities. """ params = {'count': 1} if type: params['type'] = type return int(self._get_url_json('entities/list.json', **params)['count'])
[docs] def list(self, start, end, type=None): """ List all entities. """ params = {'start': start, 'end': end} if type: params['type'] = type return self._get_url_json('entities/list.json', **params) # top n lists
[docs] def top_n_individuals(self, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top individuals, by amount contributed. """ return self._get_url_json('aggregates/indivs/top_%s.json' % limit, cycle)
[docs] def top_n_organizations(self, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top organizations, by amount contributed. """ return self._get_url_json('aggregates/orgs/top_%s.json' % limit, cycle)
[docs] def top_n_politicians(self, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top politicians, by amount received. """ return self._get_url_json('aggregates/pols/top_%s.json' % limit, cycle)
[docs] def top_n_industries(self, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top industries, by amount contributed. """ return self._get_url_json('aggregates/industries/top_%s.json' % limit, cycle)
[docs] def candidates_by_location(self, location, cycle=DEFAULT_CYCLE): """ Internal use only. Not maintained. """ return self._get_url_json('entities/race/%s.json' % location, cycle)
[docs] def election_districts(self, cycle=DEFAULT_CYCLE): """ Internal use only. Not maintained. """ return self._get_url_json('entities/race/districts.json', cycle)
[docs]class Politician(SubAPI):
[docs] def contributors(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top organizational contributors. """ return self._get_url_json('aggregates/pol/%s/contributors.json' % entity_id, cycle, limit)
[docs] def sectors(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Not maintained. """ return self._get_url_json('aggregates/pol/%s/contributors/sectors.json' % entity_id, cycle, limit)
[docs] def industries(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top contributing industries. """ return self._get_url_json('aggregates/pol/%s/contributors/industries.json' % entity_id, cycle, limit)
[docs] def local_breakdown(self, entity_id, cycle=DEFAULT_CYCLE): """ Return the breakdown of in-state vs. out-of-state contributions. """ return self._get_url_json('aggregates/pol/%s/contributors/local_breakdown.json' % entity_id, cycle)
[docs] def contributor_type_breakdown(self, entity_id, cycle=DEFAULT_CYCLE): """ Return the breakdown of individual vs. organization contributions. """ return self._get_url_json('aggregates/pol/%s/contributors/type_breakdown.json' % entity_id, cycle)
[docs] def sparkline(self, entity_id, cycle=DEFAULT_CYCLE): """ Return sparkline data for contributions received. """ return self._get_url_json('aggregates/pol/%s/sparkline.json' % entity_id, cycle)
[docs] def earmarks(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return top earmarks requested by this politician. """ return self._get_url_json('aggregates/pol/%s/earmarks.json' % entity_id, cycle, limit)
[docs] def earmarks_local_breakdown(self, entity_id, cycle=DEFAULT_CYCLE): """ Return breakdown of earmark amount for in-state vs. out-of-state projects. """ return self._get_url_json('aggregates/pol/%s/earmarks/local_breakdown.json' % entity_id, cycle)
[docs]class Individual(SubAPI):
[docs] def org_recipients(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): ''' Return the top organizations receiving contributions. ''' return self._get_url_json('aggregates/indiv/%s/recipient_orgs.json' % entity_id, cycle, limit)
[docs] def pol_recipients(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): ''' Return the top politicians receiving contributions. ''' return self._get_url_json('aggregates/indiv/%s/recipient_pols.json' % entity_id, cycle, limit)
[docs] def party_breakdown(self, entity_id, cycle=DEFAULT_CYCLE): """ Return breakdown of amount contributed to each party. """ return self._get_url_json('aggregates/indiv/%s/recipients/party_breakdown.json' % entity_id, cycle)
[docs] def registrants(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the lobbying firms that employed the individual. Only return data for individuals that are registered lobbyists. """ return self._get_url_json('aggregates/indiv/%s/registrants.json' % entity_id, cycle, limit)
[docs] def issues(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the top issues the individual lobbied on. Only return data for individuals that are registered lobbyists. """ return self._get_url_json('aggregates/indiv/%s/issues.json' % entity_id, cycle, limit)
[docs] def clients(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return the clients the individual was contracted to work for. Only return data for individuals that are registered lobbyists. """ return self._get_url_json('aggregates/indiv/%s/clients.json' % entity_id, cycle, limit)
[docs] def sparkline(self, entity_id, cycle=DEFAULT_CYCLE): """ Return sparkline data for contributions. """ return self._get_url_json('aggregates/indiv/%s/sparkline.json' % entity_id, cycle)
[docs]class Organization(SubAPI): """ Methods related to organizations or industries. """
[docs] def recipients(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return top politicians receiving contributions. """ return self._get_url_json('aggregates/org/%s/recipients.json' % entity_id, cycle, limit)
[docs] def party_breakdown(self, entity_id, cycle=DEFAULT_CYCLE): """ Return breakdown of amount contributed to each party. """ return self._get_url_json('aggregates/org/%s/recipients/party_breakdown.json' % entity_id, cycle)
[docs] def level_breakdown(self, entity_id, cycle=DEFAULT_CYCLE): """ Return breakdown of amount contributed to state vs. federal races. """ return self._get_url_json('aggregates/org/%s/recipients/level_breakdown.json' % entity_id, cycle)
[docs] def registrants(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): ''' Return lobbying firms hired. Only return data if organization is a client of lobbying firms. ''' return self._get_url_json('aggregates/org/%s/registrants.json' % entity_id, cycle, limit)
[docs] def issues(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return issues lobbied on. Only return data if organization is a client of lobbying firms. """ return self._get_url_json('aggregates/org/%s/issues.json' % entity_id, cycle, limit)
[docs] def bills(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return bills lobbied on. Only return data if organization is a client of lobbying firms. """ return self._get_url_json('aggregates/org/%s/bills.json' % entity_id, cycle, limit)
[docs] def lobbyists(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return lobbyists hired. Only return data if organization is a client of lobbying firms. """ return self._get_url_json('aggregates/org/%s/lobbyists.json' % entity_id, cycle, limit)
[docs] def registrant_clients(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return clients that hired this organization to lobby. Only return data if organization is a lobbying firm. """ return self._get_url_json('aggregates/org/%s/registrant/clients.json' % entity_id, cycle, limit)
[docs] def registrant_issues(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return issues this organization lobbied on. Only return data if organization is a lobbying firm. """ return self._get_url_json('aggregates/org/%s/registrant/issues.json' % entity_id, cycle, limit)
[docs] def registrant_bills(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return bill this organization lobbied on. Only return data if organization is a lobbying firm. """ return self._get_url_json('aggregates/org/%s/registrant/bills.json' % entity_id, cycle, limit)
[docs] def registrant_lobbyists(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return lobbyists employed. Only return data if organization is a lobbying firm. """ return self._get_url_json('aggregates/org/%s/registrant/lobbyists.json' % entity_id, cycle, limit)
[docs] def industry_orgs(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return top organizations within this industry. Only return data if entity is an industry. """ return self._get_url_json('aggregates/industry/%s/orgs.json' % entity_id, cycle, limit)
[docs] def sparkline(self, entity_id, cycle=DEFAULT_CYCLE): """ Return sparkline data for contributions. """ return self._get_url_json('aggregates/org/%s/sparkline.json' % entity_id, cycle)
[docs] def sparkline_by_party(self, entity_id, cycle=DEFAULT_CYCLE): """ Return sparkline data for contributions, broken down by recipient party. """ return self._get_url_json('aggregates/org/%s/sparkline_by_party.json' % entity_id, cycle)
[docs] def fed_spending(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return top federal grants and contracts received. Matching is based on full-text search and may include incorrect matches or miss records. Not appropriate for automatic aggregation. """ return self._get_url_json('aggregates/org/%s/fed_spending.json' % entity_id, cycle, limit)
[docs] def earmarks(self, entity_id, cycle=DEFAULT_CYCLE, limit=DEFAULT_LIMIT): """ Return top earmarks received by organization. """ return self._get_url_json('aggregates/org/%s/earmarks.json' % entity_id, cycle, limit)