Advanced Usage¶
This portion of the documentation covers some of the more advanced features of StackAPI.
Calling fetch
with various API parameters¶
The various end points all take multiple parameters to help filter the number of results you return. StackAPI will accept all of these parameters.
As an example, let’s look at the comments end point. This end point will accept the following parameters:
- page
- pagesize
- fromdate
- todate
- order
- min
- max
- sort
page
and pagesize
are handled by StackAPI through usage of the
max_pages
and page_size
values of the StackAPI
class. The others, are part of the kwargs
accepted by
fetch
.
Let’s create an example using several of these parameters. This should return
a list of questions created between March 5, 2016 and March 6, 2016 that have
a score of at least 20 and are tagged python
:
>>> from stackapi import StackAPI
>>> SITE = StackAPI('stackoverflow')
>>> questions = SITE.fetch('questions', fromdate=1457136000, todate=1457222400,
min=20, tagged='python', sort='votes')
>>> questions
{
'backoff': 0,
'has_more': False,
'items': [
{
u'accepted_answer_id': 35818398,
u'answer_count': 2,
u'creation_date': 1457186774,
u'is_answered': True,
u'last_activity_date': 1457246584,
u'last_edit_date': 1457200889,
u'link': u'http://stackoverflow.com/questions/35815093/sine-calculation-orders-of-magnitude-slower-than-cosine',
u'owner': {u'accept_rate': 80,
u'display_name': u'Finwood',
u'link': u'http://stackoverflow.com/users/1525423/finwood',
u'profile_image': u'https://i.stack.imgur.com/xkRry.png?s=128&g=1',
u'reputation': 1575,
u'user_id': 1525423,
u'user_type': u'registered'},
u'question_id': 35815093,
u'score': 22,
u'tags': [u'python', u'numpy', u'scipy', u'signal-processing'],
u'title': u'sine calculation orders of magnitude slower than cosine',
u'view_count': 404
}
],
'page': 1,
'quota_max': 300,
'quota_remaining': 171,
'total': 0
}
We can see that a single question matched our criteria.
Note: In the above example, we passed a timestamp value to the fromdate`
and ``todate
parameters. StackAPI will also allow you to pass in
datetime
objects and automatically perform this conversion for you.
StackAPI will perform this conversion to the following parameters:
- fromdate
- todate
- since
- min
- max
The min
and max
parameters are not exclusively date fields in the API.
StackAPI will only convert these to timestamps if a datetime
object is
passed.
Calling fetch
for specific IDs¶
Some of the end points accept IDs. The documentation says these are semicolon
delimited lists of values. StackAPI, however, can handle this for you. You
just need to pass a list
to the ids
keyword argument:
>>> from stackapi import StackAPI
>>> SITE = StackAPI('stackoverflow')
>>> badges = SITE.fetch('badges', ids=[222, 1306, 99999])
>>> badges
{
'backoff': 0,
'has_more': False,
'items': [
{
u'award_count': 6036,
u'badge_id': 222,
u'badge_type': u'named',
u'link': u'http://stackoverflow.com/badges/222/altruist',
u'name': u'Altruist',
u'rank': u'bronze'
},
{
u'award_count': 43954,
u'badge_id': 1306,
u'badge_type': u'named',
u'link': u'http://stackoverflow.com/badges/1306/analytical',
u'name': u'Analytical',
u'rank': u'bronze'
}
],
'page': 1,
'quota_max': 300,
'quota_remaining': 160,
'total': 0
}
Notice that we searched for 3 badges and only 2 results were returned. This is how the API operates. If an ID doesn’t exist, a result will not be returned or indicated that it has been missed. It may be important for you to compare results to what you searched for to see if any values are missing.
Another thing to notice here is that only badges
was passed as the end
point. This works because the official end point is badges/{ids}
. If you
leave the {ids}
off and it is the last part of the end point, StackAPI will
automatically add it for you. An identical call would look like this, with
{ids}
included in the end point declaration.
>>> badges = SITE.fetch('badges/{ids}', ids=[222, 1306, 99999])
If {ids}
is not at the end of the end point, then leaving it out of the
target end point is not optional. This will not work:
>>> answers = SITE.fetch('/answers/comments', ids=[1, 2, 3])
However, this will work and will return comments associated with the selected answers:
>>> answers = SITE.fetch('/answers/{ids}/comments', ids=[1, 2, 3])
Proxy Usage¶
Some users sit behind a proxy and need to get through that before accessing the internet at large. StackAPI can handle this workflow.
A failure due to a proxy may look like this:
>>> from stackapi import StackAPI, StackAPIError
>>> try:
... SITE = StackAPI('stackoverflow')
... except StackAPIError as e:
... print(e.message)
...
('Connection aborted.', error(10060, 'A connection attempt failed
because the connected party did not properly respond after a period of
time, or established connection failed because connected host has failed
to respond'))
This can be fixed, by passing a dictionary of http and https proxy addresses
when creating the StackAPI
class:
>>> from stackapi import StackAPI, StackAPIError
>>> proxies = {'http': 'http://proxy.example.com', 'https': 'http://proxy.example.com'}
>>> try:
... SITE = StackAPI('stackoverflow', proxy=proxies)
... except StackAPIError as e:
... print(e.message)
...
The two important lines are where proxies
is defined and the
modified StackAPI
initialization, which passes the
proxies
dictionary to the proxy
argument.
End points that don’t accept site
parameter¶
Not all end points accept a site parameter. This is limited to only a few
end points. In this case, you’ll receive a
StackAPIError
with
code
equal tobad_parameter
message
equal toThis method does not accept a 'site' parameter
The solution is to clear the _api_key
.
>>> from stackapi import StackAPI
>>> SITE = StackAPI('stackoverflow')
>>> SITE._api_key = None
>>> associated_users = SITE.fetch('/users/{}/associated'.format(63984), pagesize=1)
>>> associated_users
{
"items": [
{
"badge_counts": {
"bronze": 91,
"silver": 56,
"gold": 11
},
"question_count": 94,
"answer_count": 627,
"last_access_date": 1457107832,
"creation_date": 1255441385,
"account_id": 63984,
"reputation": 17438,
"user_id": 189134,
"site_url": "http://stackoverflow.com",
"site_name": "Stack Overflow"
}
],
"has_more": true,
"quota_max": 10000,
"quota_remaining": 9989
}
Send data via the API¶
StackAPI can send data to a Stack Exchange site, provided you have an application registered on StackApps and registered a token with write access.
The following example assumes that you have a registered application and
registered a user against that application. The key
value is provided
on the Stack Apps App Management page.
The token is provided when a user authorizes the application to act on their
behalf. StackAPI does not perform or support this authorization. Stack Exchange
provides three methods for performing this
authorization.
Reminder: The access_token
is per user. It is associated with a
single user. If StackAPI is acting on behalf of multiple users, the token
must be changed each time send_data
is utilized.
>>> from stackapi import StackAPI
>>> SITE = SEAPI.SEAPI('stackoverflow', key=APP_KEY, access_token=ACCESS_TOKEN)
>>> flag = SITE.send_data('comments/123/flags/add', option_id=option_id)
This block will flag comment 123
with the value of option_id
.
This value can be found by checking which options are valid for the flag.
>>> flag_options = SITE.fetch('comments/123/flags/options')
Assuming that comment 123
is valid,
this call
will return a list of valid flags. From here, you select the option_id
that matches the reason you want to flag. When you pass that via send_data
in the option_id
flag, StackAPI will issue a flag on behalf of the user
associated with the provided access_token
.