Python client for the Socrata Open Data API

Overview

PyPI version Build Status Code Coverage

sodapy

sodapy is a python client for the Socrata Open Data API.

Installation

You can install with pip install sodapy.

If you want to install from source, then clone this repository and run python setup.py install from the project root.

Requirements

At its core, this library depends heavily on the Requests package. All other requirements can be found in requirements.txt. sodapy is currently compatible with Python 3.5, 3.6, 3.7 and 3.8.

Documentation

The official Socrata Open Data API docs provide thorough documentation of the available methods, as well as other client libraries. A quick list of eligible domains to use with this API is available via the Socrata Discovery API or Socrata's Open Data Network.

This library supports writing directly to datasets with the Socrata Open Data API. For write operations that use data transformations in the Socrata Data Management Experience (the user interface for creating datasets), use the Socrata Data Management API. For more details on when to use SODA vs the Data Management API, see the Data Management API documentation. A Python SDK for the Socrata Data Management API can be found at socrata-py.

Examples

There are some jupyter notebooks in the examples directory with usage examples of sodapy in action.

Interface

Table of Contents

client

Import the library and set up a connection to get started.

>>> from sodapy import Socrata
>>> client = Socrata(
        "sandbox.demo.socrata.com",
        "FakeAppToken",
        username="[email protected]",
        password="mypassword",
        timeout=10
    )

username and password are only required for creating or modifying data. An application token isn't strictly required (can be None), but queries executed from a client without an application token will be subjected to strict throttling limits. You may want to increase the timeout seconds when making large requests. To create a bare-bones client:

>>> client = Socrata("sandbox.demo.socrata.com", None)

A client can also be created with a context manager to obviate the need for teardown:

>>> with Socrata("sandbox.demo.socrata.com", None) as client:
>>>    # do some stuff

The client, by default, makes requests over HTTPS. To modify this behavior, or to make requests through a proxy, take a look here.

datasets(limit=0, offset=0)

Retrieve datasets associated with a particular domain. The optional limit and offset keyword args can be used to retrieve a subset of the datasets. By default, all datasets are returned.

>>> client.datasets()
[{"resource" : {"name" : "Approved Building Permits", "id" : "msk6-43c6", "parent_fxf" : null, "description" : "Data of approved building/construction permits",...}, {resource : {...}}, ...]

get(dataset_identifier, content_type="json", **kwargs)

Retrieve data from the requested resources. Filter and query data by field name, id, or using SoQL keywords.

>>> client.get("nimj-3ivp", limit=2)
[{u'geolocation': {u'latitude': u'41.1085', u'needs_recoding': False, u'longitude': u'-117.6135'}, u'version': u'9', u'source': u'nn', u'region': u'Nevada', u'occurred_at': u'2012-09-14T22:38:01', u'number_of_stations': u'15', u'depth': u'7.60', u'magnitude': u'2.7', u'earthquake_id': u'00388610'}, {...}]

>>> client.get("nimj-3ivp", where="depth > 300", order="magnitude DESC", exclude_system_fields=False)
[{u'geolocation': {u'latitude': u'-15.563', u'needs_recoding': False, u'longitude': u'-175.6104'}, u'version': u'9', u':updated_at': 1348778988, u'number_of_stations': u'275', u'region': u'Tonga', u':created_meta': u'21484', u'occurred_at': u'2012-09-13T21:16:43', u':id': 132, u'source': u'us', u'depth': u'328.30', u'magnitude': u'4.8', u':meta': u'{\n}', u':updated_meta': u'21484', u'earthquake_id': u'c000cnb5', u':created_at': 1348778988}, {...}]

>>> client.get("nimj-3ivp/193", exclude_system_fields=False)
{u'geolocation': {u'latitude': u'21.6711', u'needs_recoding': False, u'longitude': u'142.9236'}, u'version': u'C', u':updated_at': 1348778988, u'number_of_stations': u'136', u'region': u'Mariana Islands region', u':created_meta': u'21484', u'occurred_at': u'2012-09-13T11:19:07', u':id': 193, u'source': u'us', u'depth': u'300.70', u'magnitude': u'4.4', u':meta': u'{\n}', u':updated_meta': u'21484', u':position': 193, u'earthquake_id': u'c000cmsq', u':created_at': 1348778988}

>>> client.get("nimj-3ivp", region="Kansas")
[{u'geolocation': {u'latitude': u'38.10', u'needs_recoding': False, u'longitude': u'-100.6135'}, u'version': u'9', u'source': u'nn', u'region': u'Kansas', u'occurred_at': u'2010-09-19T20:52:09', u'number_of_stations': u'15', u'depth': u'300.0', u'magnitude': u'1.9', u'earthquake_id': u'00189621'}, {...}]

get_all(dataset_identifier, content_type="json", **kwargs)

Read data from the requested resource, paginating over all results. Accepts the same arguments as get(). Returns a generator.

>>> client.get_all("nimj-3ivp")
<generator object Socrata.get_all at 0x7fa0dc8be7b0>

>>> for item in client.get_all("nimj-3ivp"):
...     print(item)
...
{'geolocation': {'latitude': '-15.563', 'needs_recoding': False, 'longitude': '-175.6104'}, 'version': '9', ':updated_at': 1348778988, 'number_of_stations': '275', 'region': 'Tonga', ':created_meta': '21484', 'occurred_at': '2012-09-13T21:16:43', ':id': 132, 'source': 'us', 'depth': '328.30', 'magnitude': '4.8', ':meta': '{\n}', ':updated_meta': '21484', 'earthquake_id': 'c000cnb5', ':created_at': 1348778988}
...

>>> import itertools
>>> items = client.get_all("nimj-3ivp")
>>> first_five = list(itertools.islice(items, 5))
>>> len(first_five)
5

get_metadata(dataset_identifier, content_type="json")

Retrieve the metadata associated with a particular dataset.

>>> client.get_metadata("nimj-3ivp")
{"newBackend": false, "licenseId": "CC0_10", "publicationDate": 1436655117, "viewLastModified": 1451289003, "owner": {"roleName": "administrator", "rights": [], "displayName": "Brett", "id": "cdqe-xcn5", "screenName": "Brett"}, "query": {}, "id": "songs", "createdAt": 1398014181, "category": "Public Safety", "publicationAppendEnabled": true, "publicationStage": "published", "rowsUpdatedBy": "cdqe-xcn5", "publicationGroup": 1552205, "displayType": "table", "state": "normal", "attributionLink": "http://foo.bar.com", "tableId": 3523378, "columns": [], "metadata": {"rdfSubject": "0", "renderTypeConfig": {"visible": {"table": true}}, "availableDisplayTypes": ["table", "fatrow", "page"], "attachments": ... }}

update_metadata(dataset_identifier, update_fields, content_type="json")

Update the metadata for a particular dataset. update_fields should be a dictionary containing only the metadata keys that you wish to overwrite.

Note: Invalid payloads to this method could corrupt the dataset or visualization. See this comment for more information.

>>> client.update_metadata("nimj-3ivp", {"attributionLink": "https://anothertest.com"})
{"newBackend": false, "licenseId": "CC0_10", "publicationDate": 1436655117, "viewLastModified": 1451289003, "owner": {"roleName": "administrator", "rights": [], "displayName": "Brett", "id": "cdqe-xcn5", "screenName": "Brett"}, "query": {}, "id": "songs", "createdAt": 1398014181, "category": "Public Safety", "publicationAppendEnabled": true, "publicationStage": "published", "rowsUpdatedBy": "cdqe-xcn5", "publicationGroup": 1552205, "displayType": "table", "state": "normal", "attributionLink": "https://anothertest.com", "tableId": 3523378, "columns": [], "metadata": {"rdfSubject": "0", "renderTypeConfig": {"visible": {"table": true}}, "availableDisplayTypes": ["table", "fatrow", "page"], "attachments": ... }}

download_attachments(dataset_identifier, content_type="json", download_dir="~/sodapy_downloads")

Download all attachments associated with a dataset. Return a list of paths to the downloaded files.

>>> client.download_attachments("nimj-3ivp", download_dir="~/Desktop")
    ['/Users/xmunoz/Desktop/nimj-3ivp/FireIncident_Codes.PDF', '/Users/xmunoz/Desktop/nimj-3ivp/AccidentReport.jpg']

create(name, **kwargs)

Create a new dataset. Optionally, specify keyword args such as:

  • description description of the dataset
  • columns list of fields
  • category dataset category (must exist in /admin/metadata)
  • tags list of tag strings
  • row_identifier field name of primary key
  • new_backend whether to create the dataset in the new backend

Example usage:

>>> columns = [{"fieldName": "delegation", "name": "Delegation", "dataTypeName": "text"}, {"fieldName": "members", "name": "Members", "dataTypeName": "number"}]
>>> tags = ["politics", "geography"]
>>> client.create("Delegates", description="List of delegates", columns=columns, row_identifier="delegation", tags=tags, category="Transparency")
{u'id': u'2frc-hyvj', u'name': u'Foo Bar', u'description': u'test dataset', u'publicationStage': u'unpublished', u'columns': [ { u'name': u'Foo', u'dataTypeName': u'text', u'fieldName': u'foo', ... }, { u'name': u'Bar', u'dataTypeName': u'number', u'fieldName': u'bar', ... } ], u'metadata': { u'rowIdentifier': 230641051 }, ... }

publish(dataset_identifier, content_type="json")

Publish a dataset after creating it, i.e. take it out of 'working copy' mode. The dataset id id returned from create will be used to publish.

>>> client.publish("2frc-hyvj")
{u'id': u'2frc-hyvj', u'name': u'Foo Bar', u'description': u'test dataset', u'publicationStage': u'unpublished', u'columns': [ { u'name': u'Foo', u'dataTypeName': u'text', u'fieldName': u'foo', ... }, { u'name': u'Bar', u'dataTypeName': u'number', u'fieldName': u'bar', ... } ], u'metadata': { u'rowIdentifier': 230641051 }, ... }

set_permission(dataset_identifier, permission="private", content_type="json")

Set the permissions of a dataset to public or private.

>>> client.set_permission("2frc-hyvj", "public")
<Response [200]>

upsert(dataset_identifier, payload, content_type="json")

Create a new row in an existing dataset.

>>> data = [{'Delegation': 'AJU', 'Name': 'Alaska', 'Key': 'AL', 'Entity': 'Juneau'}]
>>> client.upsert("eb9n-hr43", data)
{u'Errors': 0, u'Rows Deleted': 0, u'Rows Updated': 0, u'By SID': 0, u'Rows Created': 1, u'By RowIdentifier': 0}

Update/Delete rows in a dataset.

>>> data = [{'Delegation': 'sfa', ':id': 8, 'Name': 'bar', 'Key': 'doo', 'Entity': 'dsfsd'}, {':id': 7, ':deleted': True}]
>>> client.upsert("eb9n-hr43", data)
{u'Errors': 0, u'Rows Deleted': 1, u'Rows Updated': 1, u'By SID': 2, u'Rows Created': 0, u'By RowIdentifier': 0}

upsert's can even be performed with a csv file.

>>> data = open("upsert_test.csv")
>>> client.upsert("eb9n-hr43", data)
{u'Errors': 0, u'Rows Deleted': 0, u'Rows Updated': 1, u'By SID': 1, u'Rows Created': 0, u'By RowIdentifier': 0}

replace(dataset_identifier, payload, content_type="json")

Similar in usage to upsert, but overwrites existing data.

>>> data = open("replace_test.csv")
>>> client.replace("eb9n-hr43", data)
{u'Errors': 0, u'Rows Deleted': 0, u'Rows Updated': 0, u'By SID': 0, u'Rows Created': 12, u'By RowIdentifier': 0}

create_non_data_file(params, file_obj)

Creates a new file-based dataset with the name provided in the files tuple. A valid file input would be:

files = (
    {'file': ("gtfs2", open('myfile.zip', 'rb'))}
)
>>> with open(nondatafile_path, 'rb') as f:
>>>     files = (
>>>         {'file': ("nondatafile.zip", f)}
>>>     )
>>>     response = client.create_non_data_file(params, files)

replace_non_data_file(dataset_identifier, params, file_obj)

Same as create_non_data_file, but replaces a file that already exists in a file-based dataset.

Note: a table-based dataset cannot be replaced by a file-based dataset. Use create_non_data_file in order to replace.

>>>  with open(nondatafile_path, 'rb') as f:
>>>      files = (
>>>          {'file': ("nondatafile.zip", f)}
>>>      )
>>>      response = client.replace_non_data_file(DATASET_IDENTIFIER, {}, files)

delete(dataset_identifier, row_id=None, content_type="json")

Delete an individual row.

>>> client.delete("nimj-3ivp", row_id=2)
<Response [200]>

Delete the entire dataset.

>>> client.delete("nimj-3ivp")
<Response [200]>

close()

Close the session when you're finished.

>>> client.close()

Run tests

$ pytest

Contributing

See CONTRIBUTING.md.

Meta

This package uses semantic versioning.

Source and wheel distributions are available on PyPI. Here is how I create those releases.

python3 setup.py bdist_wheel
python3 setup.py sdist
twine upload dist/*
Issues
  • Query to return all dataset identifiers from an endpoint?

    Query to return all dataset identifiers from an endpoint?

    Hi,

    I'm not sure if I'm missing something, but can this library perform a query to return all dataset identifiers from a given endpoint, so that I can then loop through them and perform get requests?

    I could obviously just make a request to https://data.edmonton.ca/api/catalog/v1?domains=data.edmonton.ca and parse the JSON manually to get the resource ID from every top-level object, but it seems like there should be an easier way...

    opened by axfelix 16
  • Importing blob files

    Importing blob files

    I am attempting to replace a zip file in socrata. This file may be generated on a nightly basis. The Google Transit Feed System file format has a number of csv files of different schemas, so it doesn't make sense for a direct CSV upsert.

    Safe FME has provided a method for pushing blob files to Socrata. It seems to hit the not-so-documented api end point of POST https://data.texas.gov/api/imports2?method=blob&fileUploaderfile=['C:', 'myfile.zip'] with the usual header files.

    I was thinking about providing a PR that incorporates this functionality in sodapy. Do you think it would make sense to put a blob parameter in replace and upsert. If blob is true, then use the endpoint above to push the file?

    I was curious if there is a reason why api/imports2 is not used and if there are potentially other methods.

    opened by nathanhilbert 9
  • Exception: Unknown response format: application/json

    Exception: Unknown response format: application/json

    I deployed an application three months ago using sodapy. It was fully functional up until Monday, November 28. On my deployed instance, I get "502 Bad Gateway". Running locally, I get the following error:

    File "/Users/File/Path/Crime.py", line 12, in get_crimes
    crimes = client.get("cuks-n6tp",limit=3000)
    
    File "/usr/local/lib/python2.7/site-packages/sodapy/__init__.py", line 237, in get
    params=params)
    
    File "/usr/local/lib/python2.7/site-packages/sodapy/__init__.py", line 368, in _perform_request
    .format(content_type))
    
    Exception: Unknown response format: application/json
    

    I don't understand the exception. The data set is here and clearly json: https://data.sfgov.org/resource/cuks-n6tp.json

    Let me know if this is the wrong place to post this question.

    Thanks, Alex

    opened by alex-wap 8
  • Create dataset

    Create dataset

    ~~Not ready to merge yet. This is a work in progress. Just opening the pull request to encourage discussion around the implementation.~~ (Update: Ready to merge)

    I'm still new to python and would love feedback and suggestions. I figure there's also room to discuss things like columns, and the fact that creating a dataset is actually 3 HTTP requests (create, set public, publish). Here's what I have so far.

    Edit: Another thing worth discussing is the fact that this uses the new API, so /resource/asdf-asdf.json is not the correct path (it's /api/views/asdf-asdf.json). I'd make the argument for abstracting the resource in the library and only looking for the 4x4 dataset ID. This way it would be very easy to switch from the old API to the new one, even for reading/GETs. I imagine in order to make this a non-breaking change, we'd have to allow the /resource/xxxx.json usage and just trim it off the string as I've done in this pull request.

    opened by timwis 8
  • New backend option

    New backend option

    I found out today from Socrata that ?nbe=true can be used to create the dataset in the new backend. They advised that this should be used for (a) geospatial datasets, and (b) huge tabular datasets (15-20 million rows). For everything else, the old backend should be used for now, since the new backend doesn't support everything just yet (ie. export formats).

    I also removed that whitespace on empty lines that I created in my last PR. My bad.

    Note that I imagine in a few months this won't be necessary as all dataset creation will automatically be in the new backend.

    opened by timwis 8
  • don't rely on the full path anymore for more flexibility

    don't rely on the full path anymore for more flexibility

    @timwis Can you help me test that everything still works? Also, is there anything you would add/change/remove?

    opened by xmunoz 7
  • get_all() has inconsistent pagination

    get_all() has inconsistent pagination

    After running:

    results = client.get_all("y8as-bmzj")
    with open("coc test.csv", "a", newline="", encoding="utf-8") as line_file:
        csv_writer = DictWriter(line_file, fieldnames=["id","sample_site","sample_date",
                                                       "parameter","numeric_result","result_qualifier",
                                                       "formatted_result","result_units","latitude_degrees","longitude_degrees","site_key"])
        for row in data:
            csv_writer.writerow(row)      
    

    I was receiving different final files each time. Sometimes these would include duplicate rows, other times I would have rows missing. I reran my code using pagination over the OData API instead with no issues. From my debugging the only thing I could figure was that the get_all() function wasn't returning the data correctly

    opened by patrickleclair-GORDONFN 6
  • UnicodeEncodeError on exception

    UnicodeEncodeError on exception

    While uploading some data to Socrata with sodapy 1.2.0 and the upsert method, an Exception was raised due to status response, but the code failed as it seems the text coming from the server including UTF-8 characters.

    Below is the traceback

      File "/Users/secastro/miniconda/lib/python2.7/site-packages/sodapy/__init__.py", line 221, in upsert
        return self._perform_update("post", resource, payload)
      File "/Users/secastro/miniconda/lib/python2.7/site-packages/sodapy/__init__.py", line 238, in _perform_update
        data=json.dumps(payload))
      File "/Users/secastro/miniconda/lib/python2.7/site-packages/sodapy/__init__.py", line 284, in _perform_request
        _raise_for_status(response)
      File "/Users/secastro/miniconda/lib/python2.7/site-packages/sodapy/__init__.py", line 332, in _raise_for_status
        http_error_msg += ".\n\t{0}".format(more_info)
    UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffd' in position 90: ordinal not in range(128)
    

    I'm not uploading UTF-8 data, so I haven't tested specifically for that.

    opened by seb-at-nzrs 6
  • Issue with upsert/replace

    Issue with upsert/replace

    I keep getting the same error when using upsert or replace:

    Traceback (most recent call last):
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\connectionpool.py", line 384, in _make_request
        six.raise_from(e, None)
      File "<string>", line 2, in raise_from
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\connectionpool.py", line 380, in _make_request
        httplib_response = conn.getresponse()
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\http\client.py", line 1321, in getresponse
        response.begin()
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\http\client.py", line 296, in begin
        version, status, reason = self._read_status()
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\http\client.py", line 257, in _read_status
        line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\socket.py", line 589, in readinto
        return self._sock.recv_into(b)
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\contrib\pyopenssl.py", line 307, in recv_into
        raise timeout('The read operation timed out')
    socket.timeout: The read operation timed out
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\requests\adapters.py", line 449, in send
        timeout=timeout
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\connectionpool.py", line 638, in urlopen
        _stacktrace=sys.exc_info()[2])
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\util\retry.py", line 367, in increment
        raise six.reraise(type(error), error, _stacktrace)
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\packages\six.py", line 686, in reraise
        raise value
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\connectionpool.py", line 600, in urlopen
        chunked=chunked)
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\connectionpool.py", line 386, in _make_request
        self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
      File "C:\Users\tristanya\AppData\Local\Continuum\anaconda3\lib\site-packages\urllib3\connectionpool.py", line 306, in _raise_timeout
        raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value)
    urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='mydata.iadb.org', port=443): Read timed out. (read timeout=10)
    

    I have tried using csv and json as the data format, neither work. Any idea what is going on?

    opened by tarmangue 5
  • Can't access from behind proxy

    Can't access from behind proxy

    I'm trying to use python behind proxy and I get this error:

    HTTPSConnectionPool(host='hostname', port=443): Max retries exceeded with url: /api/views/hdsc-ubkz.json (Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fc509240110>: Failed to establish a new connection: [Errno 113] No route to host',))
    

    Is there a way to specify proxy settings with sodapy?

    opened by asarchami 4
  • SoQL query support for get_all()

    SoQL query support for get_all()

    While I was trying to submit a SoQL query using the get_all() method, it kept throwing an error:

    HTTPError: 400 Client Error: Bad Request.
            If $query is used, all options - [$offset] should not be specified in $query.
    

    The official documentation isn't super detailed It looks like the problem is that all options must be in the SoQL query if you use a SoQL query.

    My code using get_all is below. But you can reproduce this error with the get() method by including a query parameter with any other SoQL clause.

    I came up with a functional solution, but wasn't sure how to update the test or documentation.

    However, I thought I would open an issue before making a pull request. For most cases, filtering with the other API parameters is ok. Perhaps the simplest solution is changing the get_all() docstring to note SoQL queries aren't supported.

    import json
    from sodapy import Socrata
    
    client_params = {'domain': 'health.data.ny.gov',
                    'app_token': None,
                    'timeout': 10} 
    
    request_params = {'dataset_identifier': 'vn5v-hh5r',
                      'content_type': 'json',
                      'query': """SELECT facility_name, fac_desc_short
                                  WHERE fac_desc_short like '%HOSP%'"""}
    
    with Socrata(**client_params) as client:
        response = client.get_all(**request_params)
    
    # Iterating over the generator throws HTTPError error
    resp_list = [r for r in response]
    
    # If it actually works, put data here
    with open('query_test.json', 'w') as f:
        json.dump(resp_list, f, indent=4)
    
    opened by kuirolo 3
Owner
Cristina
ACAB
Cristina
Python: Asynchronous client for the Open-Meteo API.

Python: Asynchronous client for the Open-Meteo API. Asynchronous client for the Open-Meteo API. About Open-Meteo offers free weather forecast APIs for

Franck Nijhof 5 Jan 10, 2022
wyscoutapi is an extremely basic API client for the Wyscout API (v2 & v3) for Python

wyscoutapi wyscoutapi is an extremely basic API client for the Wyscout API (v2 & v3). Usage Install with pip install wyscoutapi. To connect to the Wys

Ben Torvaney 7 Dec 19, 2021
Beyonic API Python official client library simplified examples using Flask, Django and Fast API.

Beyonic API Python official client library simplified examples using Flask, Django and Fast API.

Harun Mbaabu Mwenda 45 Nov 18, 2021
Python API Client for Twitter API v2

?? Python Client For Twitter API v2 ?? Why Twitter Stream ? Twitter-Stream.py a python API client for Twitter API v2 now supports FilteredStream, Samp

Twitivity 17 Jan 4, 2022
Drcom-pt-client - Drcom Pt version client with refresh timer

drcom-pt-client Drcom Pt version client with refresh timer Dr.com Pt版本客户端 可用于网页认

null 3 Jan 4, 2022
A Pythonic client for the official https://data.gov.gr API.

pydatagovgr An unofficial Pythonic client for the official data.gov.gr API. Aims to be an easy, intuitive and out-of-the-box way to: find data publish

Ilias Antonopoulos 34 Dec 25, 2021
Public API client for GETTR, a "non-bias [sic] social network," designed for data archival and analysis.

GoGettr GoGettr is an API client for GETTR, a "non-bias [sic] social network." (We will not reward their domain with a hyperlink.) GoGettr is built an

Stanford Internet Observatory 46 Jan 13, 2022
Maestral is an open-source Dropbox client written in Python.

Maestral - A light-weight and open-source Dropbox client for macOS and Linux

null 2k Jan 12, 2022
Official Python client for the MonkeyLearn API. Build and consume machine learning models for language processing from your Python apps.

MonkeyLearn API for Python Official Python client for the MonkeyLearn API. Build and run machine learning models for language processing from your Pyt

MonkeyLearn 148 Dec 14, 2021
🖥️ Python - P1 Monitor API Asynchronous Python Client

??️ Asynchronous Python client for the P1 Monitor

Klaas Schoute 2 Jan 10, 2022
Design and build a wrapper for the Open Weather API current weather data service

Design and build a wrapper for the Open Weather API current weather data service that returns a city's temperature, with caching, also allowing for the temperature of the latest queried cities that are still validly cached to be retrieved.

Duan Rafael Ribeiro 1 Nov 25, 2021
Python API Client for Close

Close API A convenient Python wrapper for the Close API. API docs: http://developer.close.com Support: [email protected] Installation pip install clos

Close 51 Jan 30, 2021
Python client for CoinPayments API

pyCoinPayments - Python API client for CoinPayments Updates This library has now been converted to work with python3 This is an unofficial client for

James 24 Jan 14, 2022
DEPRECATED - Official Python Client for the Discogs API

⚠️ DEPRECATED This repository is no longer maintained. You can still use a REST client like Requests or other third-party Python library to access the

Discogs 488 Jan 7, 2022
The Foursquare API client for Python

foursquare Python client for the foursquare API. Philosophy: Map foursquare's endpoints one-to-one Clean, simple, Pythonic calls Only handle raw data,

Mike Lewis 391 Dec 2, 2021
Python Client for Instagram API

This project is not actively maintained. Proceed at your own risk! python-instagram A Python 2/3 client for the Instagram REST and Search APIs Install

Facebook Archive 2.9k Jan 11, 2022
A Python Client for News API

newsapi-python A Python client for the News API. License Provided under MIT License by Matt Lisivick. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRAN

Matt Lisivick 234 Jan 9, 2022
SmartFile API Client (Python).

A SmartFile Open Source project. Read more about how SmartFile uses and contributes to Open Source software. Summary This library includes two API cli

SmartFile 19 Jan 11, 2022
Python client for the Echo Nest API

Pyechonest Tap into The Echo Nest's Musical Brain for the best music search, information, recommendations and remix tools on the web. Pyechonest is an

The Echo Nest 648 Dec 23, 2021