API-NG включает в себя три API:
Можно поэкспериментировать с онлайн визуализаторами следующих api:
Основное:
Для ручной интерактивной авторизации у нас должны быть:
Для использования API у каждого приложения должно быть два ключа, по которым идентифицируется приложение. Один "live App Key", другой "delayed App Key". В каждом HHTP запросе в заголовке мы должны передавать один ключ. Вот так:
X-Application: APP_KEY_ASSIGNEDСоздать необходимые ключи можно следуя инструкции.
Для автономной авторизации у нас должны быть:
# -*- coding: utf-8 -*-
import requests
import json
APP_KEY_LIVE = ""
LOGIN = ""
PASSWORD = ""
def login(username, password):
# returns session token or -1 if fails
# возвращает идентификатор сессии или при неудаче -1
login_url = 'https://identitysso.betfair.com/api/certlogin'
mydata = 'username=%s&password=%s' % (username, password)
cert_files = ('certs/client-2048.crt', 'certs/client-2048.key')
headers = {
'X-Application': APP_KEY_LIVE,
'Content-Type': 'application/x-www-form-urlencoded'
}
resp = requests.post(login_url, data=mydata, cert=cert_files, headers=headers)
resp_json = resp.json()
if resp_json['loginStatus'] == 'SUCCESS':
return resp_json['sessionToken']
else:
return -1
SESSION_TOKEN = login(LOGIN, PASSWORD)
print(SESSION_TOKEN)
Дополнительная информация по теме авторизации
Пример функции выхода:
# -*- coding: utf-8 -*-
def logout():
#logout from betfair api-ng. returns string.
logout_url = 'https://identitysso.betfair.com/api/logout'
headers = {
'Accept': 'application/json',
'X-Application': APP_KEY_LIVE,
'X-Authentication': SESSION_TOKEN
}
resp = requests.post(logout_url, headers=headers)
resp_json = resp.json()
if resp_json['status'] == 'SUCCESS':
return "SUCCESS LOGOUT"
else:
raise Exception(str(resp))
Дополнительная информация по теме выхода.
В итоге получилась такая небольшая библиотека.
# -*- coding: utf-8 -*-
import requests
import json
import urllib
class APINGLib(object):
APP_KEY_LIVE = ""
def __init__(self, login, password):
self.LOGIN = login
self.PASSWORD = password
self.SESSION_TOKEN = self.login()
def login(self):
# returns session token or -1 if fails
# возвращает идентификатор сессии или при неудаче -1
login_url = 'https://identitysso.betfair.com/api/certlogin'
mydata = 'username=%s&password=%s' % (self.LOGIN, self.PASSWORD)
cert_files = ('certs/client-2048.crt', 'certs/client-2048.key')
headers = {
'X-Application': self.APP_KEY_LIVE,
'Content-Type': 'application/x-www-form-urlencoded'
}
resp = requests.post(login_url, data=mydata, cert=cert_files, headers=headers)
resp_json = resp.json()
if resp_json['loginStatus'] == 'SUCCESS':
return resp_json['sessionToken']
else:
return -1
def logout(self):
# logout from betfair api-ng. returns string.
logout_url = 'https://identitysso.betfair.com/api/logout'
headers = {
"Accept": "application/json",
"X-Application": self.APP_KEY_LIVE,
"X-Authentication": self.SESSION_TOKEN
}
resp = requests.post(logout_url, headers=headers)
resp_json = resp.json()
if resp_json['status'] == 'SUCCESS':
return "SUCCESS LOGOUT"
else:
raise Exception(str(resp))
def send_http_request(self, request):
url = "https://api.betfair.com/exchange/betting/json-rpc/v1 "
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Application': self.APP_KEY_LIVE,
'X-Authentication': self.SESSION_TOKEN
}
if type(request) == type(dict()):
request = json.dumps(request) # convert dict to json format
request1 = urllib.request.Request(url, request.encode('utf-8'), headers=headers)
resp = urllib.request.urlopen(request1)
resp_json = json.loads(resp.read().decode('utf-8'))['result']
return resp_json
Теперь с помощью нее можно уже получать доступ к актуальной информации. Выведем все события на которые можно ставить.
# -*- coding: utf-8 -*-
# file: listEventTypes.py
import APINGLib
LOGIN = ""
PASSWORD = ""
api = APINGLib.APINGLib(LOGIN, PASSWORD)
dict_event_req = {
"jsonrpc": "2.0",
"method": "SportsAPING/v1.0/listEventTypes",
"params": {
"filter": {}
},
"id": 1
}
eventTypesResponse = api.send_http_request(dict_event_req)
for event in eventTypesResponse:
print(event)
Результат должен быть примерно такой:
{'marketCount': 18, 'eventType': {'id': '468328', 'name': 'Handball'}} {'marketCount': 9051, 'eventType': {'id': '1', 'name': 'Soccer'}} {'marketCount': 522, 'eventType': {'id': '2', 'name': 'Tennis'}} {'marketCount': 74, 'eventType': {'id': '3', 'name': 'Golf'}} {'marketCount': 272, 'eventType': {'id': '4', 'name': 'Cricket'}} {'marketCount': 12, 'eventType': {'id': '5', 'name': 'Rugby Union'}} {'marketCount': 60, 'eventType': {'id': '6', 'name': 'Boxing'}} {'marketCount': 387, 'eventType': {'id': '7', 'name': 'Horse Racing'}} {'marketCount': 60, 'eventType': {'id': '8', 'name': 'Motor Sport'}} {'marketCount': 1, 'eventType': {'id': '7524', 'name': 'Ice Hockey'}} {'marketCount': 8, 'eventType': {'id': '10', 'name': 'Special Bets'}} {'marketCount': 23, 'eventType': {'id': '11', 'name': 'Cycling'}} {'marketCount': 176, 'eventType': {'id': '7522', 'name': 'Basketball'}} {'marketCount': 57, 'eventType': {'id': '1477', 'name': 'Rugby League'}} {'marketCount': 187, 'eventType': {'id': '4339', 'name': 'Greyhound Racing'}} {'marketCount': 1, 'eventType': {'id': '3088925', 'name': 'Fishing'}} {'marketCount': 24, 'eventType': {'id': '2378961', 'name': 'Politics'}} {'marketCount': 66, 'eventType': {'id': '6231', 'name': 'Financial Bets'}} {'marketCount': 9, 'eventType': {'id': '998917', 'name': 'Volleyball'}} {'marketCount': 55, 'eventType': {'id': '998918', 'name': 'Bowls'}} {'marketCount': 43, 'eventType': {'id': '26420387', 'name': 'Mixed Martial Arts'}} {'marketCount': 181, 'eventType': {'id': '3503', 'name': 'Darts'}} {'marketCount': 1, 'eventType': {'id': '72382', 'name': 'Pool'}} {'marketCount': 60, 'eventType': {'id': '2152880', 'name': 'Gaelic Games'}} {'marketCount': 2, 'eventType': {'id': '300000', 'name': 'Commonwealth Games'}} {'marketCount': 1, 'eventType': {'id': '6422', 'name': 'Snooker'}} {'marketCount': 23, 'eventType': {'id': '6423', 'name': 'American Football'}} {'marketCount': 2, 'eventType': {'id': '315220', 'name': 'Poker'}} {'marketCount': 132, 'eventType': {'id': '7511', 'name': 'Baseball'}}
Теперь выведем все события из раздела "Special Bets". Из предыдущего запроса мы знаем, что eventTypeIds его равен 10, а всего событий должно быть marketCount, т.е. 8.
# -*- coding: utf-8 -*-
# file: listMarketCatalogue.py
import APINGLib
LOGIN = ""
PASSWORD = ""
api = APINGLib.APINGLib(LOGIN, PASSWORD)
listMarket_req = {
"jsonrpc": "2.0",
"method": "SportsAPING/v1.0/listMarketCatalogue",
"params": {
"filter": {
"eventTypeIds": [10]
},
"maxResults": "100"
},
}
listMarketResponse = api.send_http_request(listMarket_req)
for event in listMarketResponse:
print(event)
У меня результат был такой:
{'totalMatched': 165520.98557999998, 'marketName': 'Winner', 'marketId': '1.114265488'} {'totalMatched': 646.6966239999999, 'marketName': 'Male or Female', 'marketId': '1.114265484'} {'totalMatched': 280.47312, 'marketName': 'Top 3', 'marketId': '1.114283805'} {'totalMatched': 850.039636, 'marketName': 'Top Female', 'marketId': '1.114283806'} {'totalMatched': 138.226, 'marketName': 'Top Male', 'marketId': '1.114283807'} {'totalMatched': 343.1020639999999, 'marketName': 'Top UK Summer Temperature 2014', 'marketId': '1.114169447'} {'totalMatched': 80758.716424, 'marketName': 'Winner', 'marketId': '1.112244045'} {'totalMatched': 8279.963588, 'marketName': 'Top 3', 'marketId': '1.112243909'}
Когда мы знаем идентификатор рынка мы можем легко получит по нему всю информацию с помощью listMarketCatalogue
# -*- coding: utf-8 -*-
# file: listMarketCatalogueAddition_example.py
import APINGLib
LOGIN = ""
PASSWORD = ""
api = APINGLib.APINGLib(LOGIN, PASSWORD)
listMarket_req = {
"jsonrpc": "2.0",
"method": "SportsAPING/v1.0/listMarketCatalogue",
"params": {
"filter": {
"marketIds": ["1.114549032"]
},
"maxResults": "10",
"marketProjection": ["COMPETITION", "EVENT", "EVENT_TYPE", "MARKET_DESCRIPTION", "RUNNER_DESCRIPTION"]
},
"id": 1
}
listMarketResponse = api.send_http_request(listMarket_req)
print("Competition: " + str(listMarketResponse[0]['competition']['name']))
print("Market Name: " + str(listMarketResponse[0]['marketName']))
print("Event: " + str(listMarketResponse[0]['event']['name']))
print("Event Type: " + str(listMarketResponse[0]['eventType']['name']))
print(listMarketResponse[0]['runners'])
Для взаимодействия нашей программы на питоне и сайта нам нужно создать сертификат SSL и ключи загрузить в наш аккаунт на betfair.
[ ssl_client ]
basicConstraints = CA:FALSE
nsCertType = client
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:London
Locality Name (eg, city) []:London
Organization Name (eg, company) [Internet Widgits Pty Ltd]:yourcompany.com
Organizational Unit Name (eg, section) []:Security Team
Common Name (e.g. server FQDN or YOUR name) []:Test API-NG Certificate
Email Address []:my.name@mydomain.com
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
http://forum.bdp.betfair.com/showthread.php?t=1224
http://forum.bdp.betfair.com/showthread.php?t=472