Author : iascchen(at)gmail(dot)com
Date : 2013-07-18
新浪微博 : @問天鼓
利用Python實現了咕咚 Codoon 運動的 API。對應API詳細說明參見 獲取咕咚運動移動應用中的數據——非官方API
代碼地址
https://github.com/iascchen/VisHealth/
使用 devices/codoon.py 即可。
依賴包
requests 當前使用版本爲 1.2.3
源代碼說明
codoonurl.py 爲 Codoon 服務請求 URL 入口生成工具。
codoon.py 爲 Codoon 運動非官方 API 的 Python 實現代碼。它的 main 方法是使用這些API的示例。
- Codoon API 被封裝在 class DeviceCodoon 中
- Codoon App 一般通過 HTTP 協議與 api.codoon.com 通訊。在進行其他訪問之前,必須先登錄。可以用 Codoon 網註冊用戶通過 HTTP Basic 協議進行登陸。正確登錄之後,這個 Token 將被存放爲 DeviceCodoon 實例中的 codoonHeaders 變量中,每次向服務器的請求,都需要將 codoonHeaders 的加載在 HTTP Header 中提供。Codoon App 還支持利用新浪微博、騰訊微博、人人網的用戶,通過OAuth協議登錄(這幾種登錄方式本文並未論述)。
- 訪問Codoon其他站,需要進行 SSO,這個SSO需要用到 Cookies, 調用 get_misc_mobile( ) 方法後,如果正確返回,包含用戶信息的 Cookies 將放在 DeviceCodoon 實例中的 codoonCookies 變量中。
- 如果函數調用之後,各函數會返回所收到的JSON文件。如果調用失敗,會拋出異常,或打出 Error Code 。
HTTP Basic 認證後的 HTTP Header
需要將認證時的所獲得 access_token 值設置到 HTTP Header:**Authorization** 裏,即可保持會話。除此之外,還需要將**Charset**設置爲 UTF-8。如:
Authorization : Bearer 4836c512060faa34793730959daa901f
Charset : UTF-8
帶參數的請求
需要向 Server 端提交參數的請求,需要採用 POST 方式傳參。比較特殊的是,在 Codoon 的接口中,需要將參數需要轉化爲 JSON 之後,放在 POST 體中再提交。
下面的 Python 代碼作爲參考示例:
startDate = "2013-06-01"
endDate = "2013-06-30"
command = "http://api.codoon.com/api/gps_statistic"
request_data = {"from_date" : fromDate , "to_date" : toDate}
response = requests.post(command , data = json.dumps(request_data), headers = self.codoonHeaders )
content = json.loads(response.content)
代碼示例
爲了方便理解,下面對原來main中的代碼進行了最簡化改寫,去掉了一些不必要的爲了輸出和驗證的代碼。
Part 1. 登陸
可以用 Codoon 網註冊用戶通過 HTTP Basic 協議進行登陸。
Codoon App 還支持利用新浪微博、騰訊微博、人人網的用戶,通過OAuth協議登錄(這幾種登錄方式本文並未論述)。
函數說明:
# 登錄
get_users_login(self , email , password )
# 獲得用戶基本信息憑證
verify_credentials(self)
參考代碼:
account = { "email" : "your@email" , "passwd" : "yourpassword" }
device = DeviceCodoon ()
# login
logined = device.get_users_login(account["email"], account["passwd"])
print device.auth_info
credentials = device.verify_credentials()
Part 2. 用戶運動成就
函數說明:
# 返回用戶的成就信息
get_user_growing_point_related(self)
# 返回用戶的運動紀
gps_highest_record(self)
# 用戶所獲得的獎章
get_user_medal(self)
# 統計信息
# 日期格式爲: yyyy-mm-dd, 如:2013-06-01
gps_statistic(self , fromDate , toDate)
參考代碼:
account = { "email" : "your@email" , "passwd" : "yourpassword" }
startDate = "2013-06-01"
endDate = "2013-06-30"
device = DeviceCodoon ()
# login
device.get_users_login(account["email"], account["passwd"])
# records
growingPoint = device.get_user_growing_point_related( )
# 紀錄
record = device.gps_highest_record( )
# 獎章
medal = device.get_user_medal( )
# 統計
statistic = device.gps_statistic( startDate , endDate )
Part 3. 運動歷史
函數說明:
# productId 爲本機 IMEI 號,寫個假的也可以
# count 應該是最大返回結果
# excluded 缺省值爲"", 格式不明
# page 翻頁信息
# isPart 是否返回GPS位置點記錄: 1 概述信息, 0 返回帶有GPS位置點的記錄
get_route_log(self , productId , count = 100 , excluded = "" , page = 1 , isPart = 1 )
# routeId 來自於 get_route_log 返回結果中的 "data"."route_id"
get_single_log(self , routeId)
參考代碼:
account = { "email" : "your@email" , "passwd" : "yourpassword" }
imei = "000000000000000"
device = DeviceCodoon ()
# login
device.get_users_login(account["email"], account["passwd"])
# 獲得用戶的運動歷史列表
routes = device.get_route_log( productId = imei , isPart = 0 )
routes = device.get_route_log( productId = imei )
# 獲得具體每次的運動軌跡
for r in routes["data"]:
routeId = r["route_id"]
route = device.get_single_log( routeId = routeId )
Part 4. 智能配件API(疑似)
函數說明:
get_mobile_portraits(self )
get_tracker_goal(self)
# endDate 截止日期,日期格式如:2013-06-30
# daysBack 整數,向前回溯多少天。
get_tracker_summary(self, endDate, daysBack )
# datestr,日期格式如:2013-06-01
get_tracker_data(self , datestr)
# datestr,日期格式如:2013-06-01
get_sleep_data(self, datestr)
參考代碼:
account = { "email" : "your@email" , "passwd" : "yourpassword" }
endDate = "2013-06-30"
checkDate = "2013-06-17"
device = DeviceCodoon ()
# login
device.get_users_login(account["email"], account["passwd"])
# mobile_portraits
portraits = device.get_mobile_portraits( )
# tracker_goal
tgoal = device.get_tracker_goal( )
# tracker_summary
tsummary = device.get_tracker_summary( endDate = endDate, daysBack = 3)
# tracker_data
tdata = device.get_tracker_data( checkDate )
# sleep_data
sleep = device.get_sleep_data( checkDate )
Part 5. 其他
函數說明:
# 約跑
# point 地理位置,形式爲兩個浮點數組成的字符串。如:"36.5,112.32"
# gender 性別 : 1 Male, 0 Female. Gender is not 0 or 1, will return all
# hobby 缺省設置爲 "",返回所有結果。服務端似乎有Bug,如果 hobby 爲中文, 會返回 500 error, :(
# page 整數,頁碼
people_surrounding(self , point , gender = 2 , hobby = None , page = 1)
# 運動計劃
# programIds 很奇葩的是被**排除在外**的 Program ID 列表,例如:如果設置爲 "3,4" ,將會返回不包括ID爲 3,4 的列表
sports_program_manifest_for_codoon(self, programIds)
# programId, 來自 sports_program_manifest_for_codoon 中的 "data"."id"
sports_program_detail(self , programId)
# 空氣質量
# cityName, 中文城市名
get_air_quality(self, cityName = None):
version_run_xml(self):
# 向 sso.codoon.com 進行認證,獲得Cookies, 如果需要訪問 www.codoon.com 的資源,就需要使用它。
def get_misc_mobile( self ):
# 訪問 http://www.codoon.com/data_v/get_user_statistic
# 得到的返回 JSON 形如: { "calorie": 82.45851, "days": 3.0, "km": 1.55822135 }
def get_user_statistic( self ):
參考代碼:
account = { "email" : "your@email" , "passwd" : "yourpassword" }
point = "36.5,112.32"
device = DeviceCodoon ()
# login
logined = device.get_users_login(account["email"], account["passwd"])
# 約跑
# Maybe Server Bug : if hobby is Chinese , server will return 500 error, :(
# ret = device.people_surrounding( point = point , gender = "1" , hobby = "跑步" , page = 1) will return 500
peoples = device.people_surrounding( point = point , gender = "1" , hobby = "") # Male
peoples = device.people_surrounding( point = point , gender = 2 , hobby = "" , page = 1) # All
# program
programs = device.sports_program_manifest_for_codoon( programIds = "3,4" ) # will return the record which ID is NOT 3 and 4
programs = device.sports_program_manifest_for_codoon( programIds = "" )
for p in programs["data"]:
programId = p["id"]
program = device.sports_program_detail( programId = programId )
# air quality
air = device.get_air_quality( cityName = "北京" )
# Latest App version
versionInfo = device.version_run_xml()
# access other info from codoon site
device.get_misc_mobile( )
# will return JSON such as { "calorie": 82.45851, "days": 3.0, "km": 1.55822135 }
wwwStatistic = device.get_user_statistic( )
祝各位玩的開心!