用于访问可汗学院挑战的内部 API
Internal APIs for getting access to Khan Academy Challenges
我正在编写一个与可汗学院集成的应用程序,我想知道是否有人知道如何获得学习者完成的挑战?
例如,我已经登录并完成了以下编程播放列表中的几个挑战。
https://www.khanacademy.org/computing/computer-programming/programming
当我查看页面本身时,它显示一些挑战标记为已完成,但是页面本身的 Chrome 开发者控制台没有显示任何 XHR Api 调用下拉该信息。
所以有没有人发现需要内部 API 才能完成哪些挑战?
根据 Ben Kraft 的建议,我试过:
'/api/v1/user/progress_summary?kind=练习'
并得到:
{"started":[],"complete":["ex8e7aac0b"]}
使用:
'/api/internal/user/kaid_688515334519823186196256/progress?dt_start=2017-08-15T00:00:00.000Z&dt_end=2018-08-25T00:00:00Z'
我有很多数据,但我不知道我可以使用哪些其他参数来归零我想要的信息(已完成 JS 入门课程的挑战)
经过一些调查,我发现了内部 API。路径如下。可以从 public /api/v1/users 调用中找到用户 KAID。 dt_start 和 dt_end 是您希望获得进度的时间范围。
/api/internal/user/[USER KAID]/progress?dt_start=2016-05-13T22:00:00.000Z&dt_end=2016-05-21T00:00:00Z&tz_offset=120&lang=en&_=1463730370107
我希望这对以后的其他人有所帮助。
我认为 /api/v1/user/progress_summary
是你最好的选择。我不确定为什么它没有在 API 资源管理器中列出,但这是内部文档:
Return progress for a content type with started and completed lists.
Takes a comma-separated `kind` param, like:
/api/v1/user/progress_summary?kind=Video,Article
and returns a dictionary that looks like:
{"complete": ["a1314267931"], "started": []}
(您还需要传递一个用户标识符,例如 kaid
,类似于其他 /api/v1/user
路由。)这些 ID 应该与您可以从主题树中获得的内容相匹配 API,如果您需要有关各个内容项的更多数据。据我所知,这与我们在主题页面上使用的数据完全相同。
这是 Khan API 示例之一的经过大量修改的版本,它完全符合您的要求(我需要相同的信息)。
import cgi
import rauth
import SimpleHTTPServer
import SocketServer
import time
import webbrowser
import requests
students = ['student1@email.com','student2@email.com']
courses = ['programming','html-css','html-css-js','programming-games-visualizations']
# You can get a CONSUMER_KEY and CONSUMER_SECRET for your app here:
# http://www.khanacademy.org/api-apps/register
CONSUMER_KEY = 'abcdefghijklmnop'
CONSUMER_SECRET = 'qrstuvwxyz123456'
CALLBACK_BASE = '127.0.0.1'
SERVER_URL = 'http://www.khanacademy.org'
VERIFIER = None
# Create the callback server that's used to set the oauth verifier after the
# request token is authorized.
def create_callback_server():
class CallbackHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
global VERIFIER
params = cgi.parse_qs(self.path.split('?', 1)[1],
keep_blank_values=False)
VERIFIER = params['oauth_verifier'][0]
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.end_headers()
self.wfile.write('OAuth request token fetched and authorized;' +
' you can close this window.')
def log_request(self, code='-', size='-'):
pass
server = SocketServer.TCPServer((CALLBACK_BASE, 0), CallbackHandler)
return server
# Make an authenticated API call using the given rauth session.
def get_api_resource(session):
start = time.time()
allProgress = []
for student in students:
print "Getting key for",student
url = SERVER_URL + '/api/v1/user?email=' + student
split_url = url.split('?', 1)
params = {}
# Separate out the URL's parameters, if applicable.
if len(split_url) == 2:
url = split_url[0]
params = cgi.parse_qs(split_url[1], keep_blank_values=False)
response = session.get(url, params=params)
studentKhanData = response.json()
try:
if student != studentKhanData['student_summary']['email']:
print "Mismatch. Khan probably returned my data instead."
print "This student probably needs to add me as a coach."
print "Skipping",student
continue
key = studentKhanData['student_summary']['key']
except TypeError as e:
print "Error:",e
print "Does this student have a Khan account?"
print "Skipping",student
continue
individualProgress = []
for course in courses:
print "Getting",course,"progress for",student
ts = int(time.time()*1000)
url = SERVER_URL + '/api/internal/user/topic-progress/' + course + '?casing=camel&userKey=' + key + '&lang=en&_=' + str(ts)
print url
split_url = url.split('?', 1)
params = {}
# Separate out the URL's parameters, if applicable.
if len(split_url) == 2:
url = split_url[0]
params = cgi.parse_qs(split_url[1], keep_blank_values=False)
response = session.get(url, params=params)
progressData = response.json()
progressArray = progressData['topicProgress']
challengeCount = 0
for activity in progressArray:
if activity['status'] == 'complete' and activity['type'] == 'challenge':
challengeCount += 1
individualProgress.append(challengeCount)
allProgress.append([student,individualProgress])
for x in allProgress:
print x
print "\n"
end = time.time()
print "\nTime: %ss\n" % (end - start)
def run_tests():
# Create an OAuth1Service using rauth.
service = rauth.OAuth1Service(
name='autoGrade',
consumer_key=CONSUMER_KEY,
consumer_secret=CONSUMER_SECRET,
request_token_url=SERVER_URL + '/api/auth2/request_token',
access_token_url=SERVER_URL + '/api/auth2/access_token',
authorize_url=SERVER_URL + '/api/auth2/authorize',
base_url=SERVER_URL + '/api/auth2')
callback_server = create_callback_server()
# 1. Get a request token.
request_token, secret_request_token = service.get_request_token(
params={'oauth_callback': 'http://%s:%d/' %
(CALLBACK_BASE, callback_server.server_address[1])})
# 2. Authorize your request token.
print "Get authorize URL"
authorize_url = service.get_authorize_url(request_token)
print authorize_url
webbrowser.open(authorize_url)
#It is possible to automate this part using selenium, but it appears to be against Khan Academy's Terms of Service
callback_server.handle_request()
callback_server.server_close()
# 3. Get an access token.
session = service.get_auth_session(request_token, secret_request_token,
params={'oauth_verifier': VERIFIER})
# Repeatedly prompt user for a resource and make authenticated API calls.
print
#while(True):
get_api_resource(session)
def main():
run_tests()
if __name__ == "__main__":
main()
我正在编写一个与可汗学院集成的应用程序,我想知道是否有人知道如何获得学习者完成的挑战?
例如,我已经登录并完成了以下编程播放列表中的几个挑战。
https://www.khanacademy.org/computing/computer-programming/programming
当我查看页面本身时,它显示一些挑战标记为已完成,但是页面本身的 Chrome 开发者控制台没有显示任何 XHR Api 调用下拉该信息。
所以有没有人发现需要内部 API 才能完成哪些挑战?
根据 Ben Kraft 的建议,我试过: '/api/v1/user/progress_summary?kind=练习' 并得到: {"started":[],"complete":["ex8e7aac0b"]}
使用: '/api/internal/user/kaid_688515334519823186196256/progress?dt_start=2017-08-15T00:00:00.000Z&dt_end=2018-08-25T00:00:00Z'
我有很多数据,但我不知道我可以使用哪些其他参数来归零我想要的信息(已完成 JS 入门课程的挑战)
经过一些调查,我发现了内部 API。路径如下。可以从 public /api/v1/users 调用中找到用户 KAID。 dt_start 和 dt_end 是您希望获得进度的时间范围。
/api/internal/user/[USER KAID]/progress?dt_start=2016-05-13T22:00:00.000Z&dt_end=2016-05-21T00:00:00Z&tz_offset=120&lang=en&_=1463730370107
我希望这对以后的其他人有所帮助。
我认为 /api/v1/user/progress_summary
是你最好的选择。我不确定为什么它没有在 API 资源管理器中列出,但这是内部文档:
Return progress for a content type with started and completed lists.
Takes a comma-separated `kind` param, like:
/api/v1/user/progress_summary?kind=Video,Article
and returns a dictionary that looks like:
{"complete": ["a1314267931"], "started": []}
(您还需要传递一个用户标识符,例如 kaid
,类似于其他 /api/v1/user
路由。)这些 ID 应该与您可以从主题树中获得的内容相匹配 API,如果您需要有关各个内容项的更多数据。据我所知,这与我们在主题页面上使用的数据完全相同。
这是 Khan API 示例之一的经过大量修改的版本,它完全符合您的要求(我需要相同的信息)。
import cgi
import rauth
import SimpleHTTPServer
import SocketServer
import time
import webbrowser
import requests
students = ['student1@email.com','student2@email.com']
courses = ['programming','html-css','html-css-js','programming-games-visualizations']
# You can get a CONSUMER_KEY and CONSUMER_SECRET for your app here:
# http://www.khanacademy.org/api-apps/register
CONSUMER_KEY = 'abcdefghijklmnop'
CONSUMER_SECRET = 'qrstuvwxyz123456'
CALLBACK_BASE = '127.0.0.1'
SERVER_URL = 'http://www.khanacademy.org'
VERIFIER = None
# Create the callback server that's used to set the oauth verifier after the
# request token is authorized.
def create_callback_server():
class CallbackHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
global VERIFIER
params = cgi.parse_qs(self.path.split('?', 1)[1],
keep_blank_values=False)
VERIFIER = params['oauth_verifier'][0]
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.end_headers()
self.wfile.write('OAuth request token fetched and authorized;' +
' you can close this window.')
def log_request(self, code='-', size='-'):
pass
server = SocketServer.TCPServer((CALLBACK_BASE, 0), CallbackHandler)
return server
# Make an authenticated API call using the given rauth session.
def get_api_resource(session):
start = time.time()
allProgress = []
for student in students:
print "Getting key for",student
url = SERVER_URL + '/api/v1/user?email=' + student
split_url = url.split('?', 1)
params = {}
# Separate out the URL's parameters, if applicable.
if len(split_url) == 2:
url = split_url[0]
params = cgi.parse_qs(split_url[1], keep_blank_values=False)
response = session.get(url, params=params)
studentKhanData = response.json()
try:
if student != studentKhanData['student_summary']['email']:
print "Mismatch. Khan probably returned my data instead."
print "This student probably needs to add me as a coach."
print "Skipping",student
continue
key = studentKhanData['student_summary']['key']
except TypeError as e:
print "Error:",e
print "Does this student have a Khan account?"
print "Skipping",student
continue
individualProgress = []
for course in courses:
print "Getting",course,"progress for",student
ts = int(time.time()*1000)
url = SERVER_URL + '/api/internal/user/topic-progress/' + course + '?casing=camel&userKey=' + key + '&lang=en&_=' + str(ts)
print url
split_url = url.split('?', 1)
params = {}
# Separate out the URL's parameters, if applicable.
if len(split_url) == 2:
url = split_url[0]
params = cgi.parse_qs(split_url[1], keep_blank_values=False)
response = session.get(url, params=params)
progressData = response.json()
progressArray = progressData['topicProgress']
challengeCount = 0
for activity in progressArray:
if activity['status'] == 'complete' and activity['type'] == 'challenge':
challengeCount += 1
individualProgress.append(challengeCount)
allProgress.append([student,individualProgress])
for x in allProgress:
print x
print "\n"
end = time.time()
print "\nTime: %ss\n" % (end - start)
def run_tests():
# Create an OAuth1Service using rauth.
service = rauth.OAuth1Service(
name='autoGrade',
consumer_key=CONSUMER_KEY,
consumer_secret=CONSUMER_SECRET,
request_token_url=SERVER_URL + '/api/auth2/request_token',
access_token_url=SERVER_URL + '/api/auth2/access_token',
authorize_url=SERVER_URL + '/api/auth2/authorize',
base_url=SERVER_URL + '/api/auth2')
callback_server = create_callback_server()
# 1. Get a request token.
request_token, secret_request_token = service.get_request_token(
params={'oauth_callback': 'http://%s:%d/' %
(CALLBACK_BASE, callback_server.server_address[1])})
# 2. Authorize your request token.
print "Get authorize URL"
authorize_url = service.get_authorize_url(request_token)
print authorize_url
webbrowser.open(authorize_url)
#It is possible to automate this part using selenium, but it appears to be against Khan Academy's Terms of Service
callback_server.handle_request()
callback_server.server_close()
# 3. Get an access token.
session = service.get_auth_session(request_token, secret_request_token,
params={'oauth_verifier': VERIFIER})
# Repeatedly prompt user for a resource and make authenticated API calls.
print
#while(True):
get_api_resource(session)
def main():
run_tests()
if __name__ == "__main__":
main()