{"id":15963215,"url":"https://github.com/bpazy/my_running_page","last_synced_at":"2026-06-17T08:32:04.509Z","repository":{"id":156867107,"uuid":"623281028","full_name":"Bpazy/my_running_page","owner":"Bpazy","description":"Make your own running home page","archived":false,"fork":false,"pushed_at":"2024-08-06T03:10:14.000Z","size":36071,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-22T21:43:25.067Z","etag":null,"topics":["codoon","data-visualization","garmin","gpx","keep","nike","strava"],"latest_commit_sha":null,"homepage":"https://running.ziyuan360.host","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bpazy.png","metadata":{"files":{"readme":"README-CN.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-04T03:57:44.000Z","updated_at":"2024-08-06T03:10:18.000Z","dependencies_parsed_at":"2024-08-06T06:06:47.655Z","dependency_job_id":"69489d74-4ef0-4318-8e6b-4437b83b7c29","html_url":"https://github.com/Bpazy/my_running_page","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Bpazy/my_running_page","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bpazy%2Fmy_running_page","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bpazy%2Fmy_running_page/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bpazy%2Fmy_running_page/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bpazy%2Fmy_running_page/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bpazy","download_url":"https://codeload.github.com/Bpazy/my_running_page/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bpazy%2Fmy_running_page/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34441283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codoon","data-visualization","garmin","gpx","keep","nike","strava"],"created_at":"2024-10-07T16:23:14.265Z","updated_at":"2026-06-17T08:32:04.491Z","avatar_url":"https://github.com/Bpazy.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![running_page](https://socialify.git.ci/yihong0618/running_page/image?description=1\u0026font=Inter\u0026forks=1\u0026issues=1\u0026language=1\u0026logo=https%3A%2F%2Fraw.githubusercontent.com%2Fshaonianche%2Fgallery%2Fmaster%2Frunning_page%2Frunning_page_logo_150*150.jpg\u0026owner=1\u0026pulls=1\u0026stargazers=1\u0026theme=Light)\n\n# [这里是白银越野赛全部 21 位逝者的故事](https://github.com/yihong0618/running_page/issues/135)\n\nR.I.P. 希望大家都能健康顺利的跑过终点，逝者安息。\n\n# [打造个人跑步主页](https://yihong.run/running)\n\n[English](README.md) | 简体中文 | [Wiki](https://wiki.mfydev.run/)\n\n\u003cdetails\u003e\n\u003csummary\u003eGIF 展示\u003c/summary\u003e\n\n![running_page](https://user-images.githubusercontent.com/15976103/98808834-c02f1d80-2457-11eb-9a7c-70e91faa5e30.gif)\n\n\u003c/details\u003e\n\n## [大家的跑步主页展示](https://github.com/yihong0618/running_page/issues/12)\n\n\u003cdetails\u003e\n\u003csummary\u003eRunning page runners\u003c/summary\u003e\n\n| Runner                                            | page                                           | App       |\n| ------------------------------------------------- | ---------------------------------------------- | --------- |\n| [zhubao315](https://github.com/zhubao315)         | \u003chttps://zhubao315.github.io/running\u003e          | Strava    |\n| [shaonianche](https://github.com/shaonianche)     | \u003chttps://run.duanfei.org\u003e                      | Strava    |\n| [yihong0618](https://github.com/yihong0618)       | \u003chttps://yihong.run\u003e                           | Nike      |\n| [superleeyom](https://github.com/superleeyom)     | \u003chttps://running.leeyom.top\u003e                   | Nike      |\n| [geekplux](https://github.com/geekplux)           | \u003chttps://activities.geekplux.com\u003e              | Nike      |\n| [guanlan](https://github.com/guanlan)             | \u003chttps://grun.vercel.app\u003e                      | Strava    |\n| [tuzimoe](https://github.com/tuzimoe)             | \u003chttps://run.tuzi.moe\u003e                         | Nike      |\n| [ben_29](https://github.com/ben-29)               | \u003chttps://running.ben29.xyz\u003e                    | Strava    |\n| [kcllf](https://github.com/kcllf)                 | \u003chttps://running-tau.vercel.app\u003e               | Garmin-cn |\n| [mq](https://github.com/MQ-0707)                  | \u003chttps://running-iota.vercel.app\u003e              | Keep      |\n| [zhaohongxuan](https://github.com/zhaohongxuan)   | \u003chttps://zhaohongxuan.github.io/workouts\u003e      | Strava    |\n| [yvetterowe](https://github.com/yvetterowe)       | \u003chttps://run.haoluo.io\u003e                        | Strava    |\n| [love-exercise](https://github.com/KaiOrange)     | \u003chttps://run.kai666666.top\u003e                    | Keep      |\n| [zstone12](https://github.com/zstone12)           | \u003chttps://running-page.zstone12.vercel.app\u003e     | Keep      |\n| [Lax](https://github.com/Lax)                     | \u003chttps://lax.github.io/running\u003e                | Keep      |\n| [lusuzi](https://github.com/lusuzi)               | \u003chttps://running.lusuzi.vercel.app\u003e            | Nike      |\n| [wh1994](https://github.com/wh1994)               | \u003chttps://run4life.fun\u003e                         | Garmin    |\n| [liuyihui](https://github.com/YiHui-Liu)          | \u003chttps://run.foolishfox.cn\u003e                    | Keep      |\n| [sunyunxian](https://github.com/sunyunxian)       | \u003chttps://sunyunxian.github.io/running_page\u003e    | Strava    |\n| [AhianZhang](https://github.com/AhianZhang)       | \u003chttps://running.ahianzhang.com\u003e               | Nike      |\n| [L1cardo](https://github.com/L1cardo)             | \u003chttps://run.licardo.cn\u003e                       | Nike      |\n| [luckylele666](https://github.com/luckylele666)   | \u003chttps://0000928.xyz\u003e                          | Strava    |\n| [MFYDev](https://github.com/MFYDev)               | \u003chttps://mfydev.run\u003e                           | Garmin-cn |\n| [Oysmart](https://github.com/oysmart)             | \u003chttps://run.ouyang.wang\u003e                      | Garmin-cn |\n| [Eished](https://github.com/eished)               | \u003chttps://run.iknow.fun\u003e                        | Keep      |\n| [Liuxin](https://github.com/liuxindtc)            | \u003chttps://liuxin.run\u003e                           | Nike      |\n| [loucx](https://github.com/loucx)                 | \u003chttps://loucx.github.io/running\u003e              | Nike      |\n| [winf42](https://github.com/winf42)               | \u003chttps://winf42.github.io\u003e                     | Garmin-cn |\n| [sun0225SUN](https://github.com/sun0225SUN)       | \u003chttps://run.sunguoqi.com\u003e                     | Nike      |\n| [Zhan](https://www.zlog.in/about)                 | \u003chttps://run.zlog.in\u003e                          | Nike      |\n| [Dennis](https://run.domon.cn)                    | \u003chttps://run.domon.cn\u003e                         | Garmin-cn |\n| [hanpei](https://running.nexts.top)               | \u003chttps://running.nexts.top\u003e                    | Garmin-cn |\n| [liugezhou](https://github.com/liugezhou)         | \u003chttps://run.liugezhou.online\u003e                 | Strava    |\n| [zhubao315](https://github.com/zhubao315)         | \u003chttps://zhubao315.github.io/running\u003e          | Strava    |\n| [Jason Tan](https://github.com/Jason-cqtan)       | \u003chttps://jason-cqtan.github.io/running_page\u003e   | Nike      |\n| [Conge](https://github.com/conge)                 | \u003chttps://conge.github.io/running_page\u003e         | Strava    |\n| [cvvz](https://github.com/cvvz)                   | \u003chttps://cvvz.github.io/running\u003e               | Strava    |\n| [zHElEARN](https://github.com/zHElEARN)           | \u003chttps://workouts.zhelearn.com\u003e                | Strava    |\n| [Rhfeng](https://sport.frh.life)                  | \u003chttps://sport.frh.life\u003e                       | Garmin-cn |\n| [Ym9i](https://github.com/Ym9i)                   | \u003chttps://bobrun.vercel.app/\u003e                   | Strava    |\n| [jianchengwang](https://github.com/jianchengwang) | \u003chttps://jianchengwang.github.io/running_page\u003e | Suunto    |\n| [fxbin](https://github.com/fxbin)                 | \u003chttps://fxbin.github.io/sport-records/\u003e       | Keep      |\n| [shensl4499](https://github.com/shensl4499)       | \u003chttps://waner.run\u003e                            | codoon    |\n| [haowei93](https://github.com/haowei93)           | \u003chttps://haowei93.github.io/\u003e                  | gpx       |\n| [stevenash0822](https://github.com/stevenash0822) | \u003chttps://run.imangry.xyz/\u003e                     | Strava    |\n| [Vint](https://github.com/VintLin)                | \u003chttps://vinton.store/Running/\u003e                | Keep      |\n| [Muyids](https://github.com/muyids)               | \u003chttps://muyids.github.io/running\u003e             | Garmin-cn |\n| [Gao Hao](https://github.com/efish2002)           | \u003chttps://efish2002.github.io/running_page/\u003e    | Garmin-cn |\n| [Jinlei](https://github.com/iamjinlei0312)        | \u003chttps://jinlei.run/\u003e                          | AW-GPX    |\n| [Ray Wang](https://github.com/raywangsy)          | \u003chttps://run.raywang.pro/\u003e                     | Garmin    |\n| [RealTiny656](https://github.com/tiny656)         | \u003chttps://tiny656.github.io/running_page/\u003e      | JoyRun    |\n| [EINDEX](https://github.com/eindex)               | \u003chttps://workouts.eindex.me/\u003e                  | Strava/Nike|\n| [Melt](https://github.com/fpGHwd)                 | \u003chttps://running.autove.dev/\u003e                  | Strava    |\n| [deepinwine](https://github.com/deepinwine)       | \u003chttps://deepin.autove.dev/\u003e                   | Garmin-cn |\n\n\u003c/details\u003e\n\n## 它是怎么工作的\n\n![image](https://user-images.githubusercontent.com/15976103/105784027-e1ad9900-5fb2-11eb-9479-372be21482f1.png)\n\n## 特性\n\n1. GitHub Actions 管理自动同步跑步进程及自动生成新的页面\n2. Gatsby 生成的静态网页，速度快\n3. 支持 Vercel(推荐) 和 GitHub Pages 自动部署\n4. React Hooks\n5. Mapbox 进行地图展示\n6. Nike 及 Runtastic(Adidas Run) 以及佳明（佳明中国）及 Keep 等，自动备份 gpx 数据，方便备份及上传到其它软件\n\n\u003e 因为数据存在 gpx 和 data.db 中，理论上支持几个软件一起，你可以把之前各类 app 的数据都同步到这里（建议本地同步，之后 actions 选择正在用的 app）\n\n\u003e 注：如果你不想公开数据，可以选择 strava 的模糊处理，或 private 仓库。\n\n\u003cdetails\u003e\n\u003csummary\u003e缩放地图彩蛋\u003c/summary\u003e\n\n![image](https://user-images.githubusercontent.com/15976103/95644909-a31bcd80-0aec-11eb-9270-869b0a94f59f.png)\n\n\u003c/details\u003e\n\n## 支持\n\n- **[Strava](#strava)**\n- **[Nike Run Club](#nike-run-club)**\n- **[Garmin](#garmin)**\n- **[Garmin-cn](#garmin-cn-大陆用户请用这个)**\n- **[Keep](#keep)**\n- **[悦跑圈](#joyrun悦跑圈，因悦跑圈限制单个设备原因，无法自动化)**\n- **[咕咚](#codoon咕咚，因咕咚限制单个设备原因，无法自动化)**\n- **[郁金香运动](#tulipsport)**\n- **[GPX](#gpx)**\n- **[TCX](#tcx)**\n- **[FIT](#fit)**\n- **[Tcx+Strava(upload all tcx data to strava)](#tcx_to_strava)**\n- **[Gpx+Strava(upload all tcx data to strava)](#gpx_to_strava)**\n- **[Nike+Strava(Using NRC Run, Strava backup data)](#nikestrava)**\n- **[Garmin_to_Strava(Using Garmin Run, Strava backup data)](#garmin_to_strava)**\n- **[Strava_to_Garmin(Using Strava Run, Garmin backup data)](#strava_to_garmin)**\n\n## 视频教程\n\n- https://www.youtube.com/watch?v=reLiY9p8EJk\n- https://www.youtube.com/watch?v=VdNkFxTX5QQ\n\n## 下载\n\n```\ngit clone https://github.com/yihong0618/running_page.git --depth=1\n```\n\n## 安装及测试 (node \u003e= 14.15.0 python \u003e= 3.7)\n\n```\npip3 install -r requirements.txt\nyarn install\nyarn develop\n```\n\n访问 \u003chttp://localhost:8000/\u003e 查看\n\n## Docker\n\n```\n#构建\n# NRC\ndocker build -t running_page:latest . --build-arg app=NRC --build-arg nike_refresh_token=\"\"\n# Garmin\ndocker build -t running_page:latest . --build-arg app=Garmin --build-arg email=\"\"  --build-arg password=\"\"\n# Garmin-CN\ndocker build -t running_page:latest . --build-arg app=Garmin-CN --build-arg email=\"\"  --build-arg password=\"\"\n# Strava\ndocker build -t running_page:latest . --build-arg app=Strava --build-arg client_id=\"\"  --build-arg client_secret=\"\"  --build-arg refresh_token=\"\"\n#Nike_to_Strava\ndocker build -t running_page:latest . --build-arg app=Nike_to_Strava  --build-arg nike_refresh_token=\"\" --build-arg client_id=\"\"  --build-arg client_secret=\"\"  --build-arg refresh_token=\"\"\n\n#启动\ndocker run -itd -p 80:80   running_page:latest\n\n#访问\n访问 ip:80 查看\n\n```\n\n## 替换 `src/utils/const.js` 文件中的 Mapbox token\n\n\u003e 建议有能力的同学把代码中的 Mapbox token 自己的 [Mapbox token](https://www.mapbox.com/)\n\n```javascript\nconst MAPBOX_TOKEN =\n  'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';\n```\n\n### 如果你是海外用户请更改 `IS_CHINESE = false` in `src/utils/const.js`\n\n## 一些个性化选项\n\n- 在仓库目录下找到 `gatsby-config.js`，找到以下内容并修改成你自己想要的。\n\n```javascript\nsiteMetadata: {\n  siteTitle: 'Running Page', #网站标题\n  siteUrl: 'https://yihong.run', #网站域名\n  logo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTtc69JxHNcmN1ETpMUX4dozAgAN6iPjWalQ\u0026usqp=CAU', #左上角LOGO\n  description: 'Personal site and blog',\n  navLinks: [\n    {\n      name: 'Blog', #右上角导航名称\n      url: 'https://yihong.run/running', #右上角导航链接\n    },\n    {\n      name: 'About',\n      url: 'https://github.com/yihong0618/running_page/blob/master/README-CN.md',\n    },\n  ],\n},\n```\n\n- 修改 `src/utils/const.js` 文件中的样式：\n\n```javascript\n// styling: 关闭虚线：设置为 `false`\nconst USE_DASH_LINE = true;\n// styling: 透明度：[0, 1]\nconst LINE_OPACITY = 0.4;\n```\n\n- 隐私保护：\n\n设置下面环境变量：\n\n```shell\nIGNORE_START_END_RANGE = 200 # 忽略每个 polyline 的起点和终点的长度（单位：米）。\n\nIGNORE_RANGE = 200 # 忽略下面 polyline 中每个点的距离的圆圈（单位：米）。\nIGNORE_POLYLINE = ktjrFoemeU~IorGq}DeB # 包含要忽略的点的折线。 \n\n# 在保存到数据库之前进行过滤，你会丢失一些数据，但可以保护你的隐私，如果你使用的是公共仓库，建议设置为1。不设置可关闭。\nIGNORE_BEFORE_SAVING = 1\n```\n\n你可一用[这个](https://developers.google.com/maps/documentation/utilities/polylineutility)，来制作你的 `IGNORE_POLYLINE`。如果你在中国，请使用卫星图制作，避免火星坐标漂移。\n\n## 下载您的 Nike Run Club/Strava/Garmin/Garmin-cn/Keep 数据，[别忘了在 `total` 页面生成可视化 SVG](#total-data-analysis)\n\n### GPX\n\n\u003cdetails\u003e\n\u003csummary\u003eMake your \u003ccode\u003eGPX\u003c/code\u003e data\u003c/summary\u003e\n\u003cbr\u003e\n\n把其它软件生成的 gpx files 拷贝到 GPX_OUT 之后运行\n\n```python\npython3(python) scripts/gpx_sync.py\n```\n\n\u003c/details\u003e\n\n### TCX\n\n\u003cdetails\u003e\n\u003csummary\u003eMake your \u003ccode\u003eTCX\u003c/code\u003e data\u003c/summary\u003e\n\u003cbr\u003e\n\n把其它软件生成的 tcx files 拷贝到 TCX_OUT 之后运行\n\n```python\npython3(python) scripts/tcx_sync.py\n```\n\n\u003c/details\u003e\n\n### FIT\n\n\u003cdetails\u003e\n\u003csummary\u003eMake your \u003ccode\u003eFIT\u003c/code\u003e data\u003c/summary\u003e\n\u003cbr\u003e\n\n把其它软件生成的 fit files 拷贝到 FIT_OUT 之后运行\n\n```python\npython3(python) scripts/fit_sync.py\n```\n\n\u003c/details\u003e\n\n### Keep\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Keep 数据\u003c/summary\u003e\n\n\u003e 确保自己的账号能用手机号 + 密码登陆 (不要忘记添加 secret 和更改自己的账号，在 GitHub Actions 中), 注：海外手机号需要换成国内 +86 的手机号\n\n```python\npython3(python) scripts/keep_sync.py ${your mobile} ${your password}\n```\n\n示例：\n\n```python\npython3(python) scripts/keep_sync.py 13333xxxx example\n```\n\n\u003e 注：我增加了 keep 可以导出 gpx 功能（因 keep 的原因，距离和速度会有一定缺失）, 执行如下命令，导出的 gpx 会加入到 GPX_OUT 中，方便上传到其它软件\n\n```python\npython3(python) scripts/keep_sync.py ${your mobile} ${your password} --with-gpx\n```\n\n示例：\n\n```python\npython3(python) scripts/keep_sync.py 13333xxxx example --with-gpx\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e路线偏移修正\u003c/summary\u003e\n\n如果您得到的运动路线与实际路线对比有整体偏移，可以修改代码中的参数进行修正\n\n\u003e 注：Keep 目前采用的是 GCJ-02 坐标系，因此导致得到运动数据在使用 WGS-84 坐标系的平台（Mapbox、佳明等）中显示轨迹整体偏移\n\n- 修改 `scripts/keep_sync.py` 文件中的参数：\n\n```python\n# If your points need trans from gcj02 to wgs84 coordinate which use by Mappbox\nTRANS_GCJ02_TO_WGS84 = True\n```\n\n\u003c/details\u003e\n\n### JoyRun（悦跑圈）\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的悦跑圈数据\u003c/summary\u003e\n\n获取登陆验证码：\n\n确保自己的账号能用手机号 + 验证码登陆\n\n点击获取验证码\n\n\u003e 注：不要在手机输入验证码，拿到验证码就好，用这个验证码放到下方命令中\n\n![image](https://user-images.githubusercontent.com/15976103/102352588-e3af3000-3fe2-11eb-8131-14946b0262eb.png)\n\n```python\npython3(python) scripts/joyrun_sync.py ${your mobile} ${your 验证码}\n```\n\n示例：\n\n```python\npython3(python) scripts/joyrun_sync.py 13333xxxx xxxx\n```\n\n\u003e 注：我增加了 joyrun 可以导出 gpx 功能，执行如下命令，导出的 gpx 会加入到 GPX_OUT 中，方便上传到其它软件\n\n```python\npython3(python) scripts/joyrun_sync.py ${your mobile} ${your 验证码} --with-gpx\n```\n\n示例：\n\n```python\npython3(python) scripts/joyrun_sync.py 13333xxxx example --with-gpx\n```\n\n\u003e 注：因为验证码有过期时间，我增加了 cookie uid sid 登陆的方式，uid 及 sid 在您登陆过程中会在控制台打印出来\n\n![image](https://user-images.githubusercontent.com/15976103/102354069-05a9b200-3fe5-11eb-9b30-221c32bbc607.png)\n\n示例：\n\n```python\npython3(python) scripts/joyrun_sync.py 1393xx30xxxx 97e5fe4997d20f9b1007xxxxx --from-uid-sid --with-gpx\n```\n\n\u003c/details\u003e\n\n### Codoon（咕咚）\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的咕咚数据\u003c/summary\u003e\n\n```python\npython3(python) scripts/codoon_sync.py ${your mobile or email} ${your password}\n```\n\n示例：\n\n```python\npython3(python) scripts/codoon_sync.py 13333xxxx xxxx\n```\n\n\u003e 注：我增加了 Codoon 可以导出 gpx 功能，执行如下命令，导出的 gpx 会加入到 GPX_OUT 中，方便上传到其它软件\n\n```python\npython3(python) scripts/codoon_sync.py ${your mobile or email} ${your password} --with-gpx\n```\n\n示例：\n\n```python\npython3(python) scripts/codoon_sync.py 13333xxxx xxxx --with-gpx\n```\n\n\u003e 注：因为登录 token 有过期时间限制，我增加了 refresh_token\u0026user_id 登陆的方式，refresh_token 及 user_id 在您登陆过程中会在控制台打印出来\n\n![image](https://user-images.githubusercontent.com/6956444/105690972-9efaab00-5f37-11eb-905c-65a198ad2300.png)\n\n示例：\n\n```python\npython3(python) scripts/codoon_sync.py 54bxxxxxxx fefxxxxx-xxxx-xxxx --from-auth-token\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e路线偏移修正\u003c/summary\u003e\n\n如果您得到的运动路线与实际路线对比有整体偏移，可以修改代码中的参数进行修正\n\n\u003e 注：咕咚最初采用 GCJ-02 坐标系，在 2014 年 3 月份左右升级为 WGS-84 坐标系，导致升级之前的运动数据在使用 WGS-84 坐标系的平台（Mapbox、佳明等）中显示轨迹整体偏移\n\n- 修改 `scripts/codoon_sync.py` 文件中的参数：\n\n\u003e 注：TRANS_END_DATE 需要根据您的实际情况设定，程序会修正这一天之前的运动记录\n\n```python\n# If your points need trans from gcj02 to wgs84 coordinate which use by Mappbox\nTRANS_GCJ02_TO_WGS84 = True\n# trans the coordinate data until the TRANS_END_DATE, work with TRANS_GCJ02_TO_WGS84 = True\nTRANS_END_DATE = \"2014-03-24\"\n```\n\n\u003c/details\u003e\n\n### TulipSport\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的郁金香运动数据\u003c/summary\u003e\n\n\u003e 郁金香运动数据的获取方式采用开放平台授权模式，通过访问[RunningPage 授权页面](https://tulipsport.rdshoep.com)获取账号 TOKEN(不会过期，只能访问 2021 年之后的数据)，并在仓库的 GitHub Actions 环境配置中添加`TULIPSPORT_TOKEN`配置。\n\n```python\npython3(python) scripts/tulipsport_sync.py ${tulipsport_token}\n```\n\n示例：\n\n```python\npython3(python) scripts/tulipsport_sync.py nLgy****RyahI\n```\n\n\u003c/details\u003e\n\n### Garmin\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Garmin 数据\u003c/summary\u003e\n\u003cbr\u003e\n如果你只想同步跑步数据增加命令 --only-run\n\n如果你想同步 `tcx` 格式，增加命令 --tcx\n\n如果你想同步 `fit` 格式，增加命令 --fit\n\n```python\npython3(python) scripts/garmin_sync.py ${your email} ${your password}\n```\n\n示例：\n\n```python\npython3(python) scripts/garmin_sync.py example@gmail.com example\n```\n\n\u003c/details\u003e\n\n### Garmin-CN (大陆用户请用这个)\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Garmin-CN 数据\u003c/summary\u003e\n\n如果你只想同步跑步数据请增加 --only-run\n\n如果你想同步 `tcx` 格式，增加命令 --tcx\n\n如果你想同步 `fit` 格式，增加命令 --fit\n\n```python\npython3(python) scripts/garmin_sync.py ${your email} ${your password} --is-cn\n```\n\n示例：\n\n```python\npython3(python) scripts/garmin_sync.py example@gmail.com example --is-cn\n```\n\n仅同步跑步数据：\n\n```python\npython3(python) scripts/garmin_sync.py example@gmail.com example --is-cn --only-run\n```\n\n\u003c/details\u003e\n\n### Nike Run Club\n\n\u003cdetails\u003e\n\u003csummary\u003e获取 Nike Run Club 数据\u003c/summary\u003e\n\n\u003e 请注意：当您选择将 running_page 部署在自己的服务器上时，由于 Nike 已经封禁了一部分 IDC 的服务器 IP 段，您的服务器可能不能正常同步 Nike Run Club 的数据并显示 `403 error` ，这时您将不得不选择其他的托管方式。\n\n获取 Nike 的 refresh_token\n\n1. 登录 [Nike](https://www.nike.com) 官网\n2. In Developer -\u003e Application-\u003e Storage -\u003e https:unite.nike.com 中找到 refresh_token\n\n![image](https://user-images.githubusercontent.com/15976103/94448123-23812b00-01dd-11eb-8143-4b0839c31d90.png) 3. 在项目根目录下执行：\n\n```python\npython3(python) scripts/nike_sync.py ${nike refresh_token}\n```\n\n示例：\n\n```python\npython3(python) scripts/nike_sync.py eyJhbGciThiMTItNGIw******\n```\n\n![example img](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/nike_sync_%20example.png)\n\n\u003c/details\u003e\n\n### Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e获取 Strava 数据\u003c/summary\u003e\n\n1. 注册/登陆 [Strava](https://www.strava.com/) 账号\n2. 登陆成功后打开 [Strava Developers](http://developers.strava.com) -\u003e [Create \u0026 Manage Your App](https://strava.com/settings/api)\n\n3. 创建 `My API Application`\n   输入下列信息：\n   ![My API Application](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/strava_settings_api.png)\n   创建成功：\n   ![](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/created_successfully_1.png)\n4. 使用以下链接请求所有权限\n   将 ${your_id} 替换为 My API Application 中的 Client ID 后访问完整链接\n\n```\nhttps://www.strava.com/oauth/authorize?client_id=${your_id}\u0026response_type=code\u0026redirect_uri=http://localhost/exchange_token\u0026approval_prompt=force\u0026scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write\n```\n\n![get_all_permissions](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/get_all_permissions.png)\n\n5. 提取授权后返回链接中的 code 值\n   例如：\n\n```\nhttp://localhost/exchange_token?state=\u0026code=1dab37edd9970971fb502c9efdd087f4f3471e6e\u0026scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all\n```\n\n`code` 数值为：\n\n```\n1dab37edd9970971fb502c9efdd087f4f3471e6\n```\n\n![get_code](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/get_code.png) 6. 使用 Client_id、Client_secret、Code 请求 refresh_token\n在 `终端/iTerm` 中执行：\n\n```\ncurl -X POST https://www.strava.com/oauth/token \\\n-F client_id=${Your Client ID} \\\n-F client_secret=${Your Client Secret} \\\n-F code=${Your Code} \\\n-F grant_type=authorization_code\n```\n\n示例：\n\n```\ncurl -X POST https://www.strava.com/oauth/token \\\n-F client_id=12345 \\\n-F client_secret=b21******d0bfb377998ed1ac3b0 \\\n-F code=d09******b58abface48003 \\\n-F grant_type=authorization_code\n```\n\n![get_refresh_token](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/get_refresh_token.png)\n\n7. 同步数据至 Strava\n   在项目根目录执行：\n\n\u003e 第一次同步 Strava 数据时需要更改在 strava_sync.py 中的第 12 行代码 False 改为 True，运行完成后，再改为 False。\n\n如果你只想同步跑步数据增加命令 --only-run\n```python\npython3(python) scripts/strava_sync.py ${client_id} ${client_secret} ${refresh_token}\n```\n\n其他资料参见\n\u003chttps://developers.strava.com/docs/getting-started\u003e\n\u003chttps://github.com/barrald/strava-uploader\u003e\n\u003chttps://github.com/strava/go.strava\u003e\n\n\u003c/details\u003e\n\n### TCX_to_Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e上传所有的 tcx 格式的跑步数据到 strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 strava 的步骤\n2. 把 tcx 文件全部拷贝到 TCX_OUT 中\n3. 在项目根目录下执行：\n\n```python\npython3(python) scripts/tcx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}\n```\n\n示例：\n\n```python\npython3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx\n或\npython3(python) scripts/tcx_to_strava_sync.py xxx xxx xxx --all\n```\n\n4. 如果你已经上传过需要跳过判断增加参数 `--all`\n\n\u003c/details\u003e\n\n### GPX_to_Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e上传所有的 gpx 格式的跑步数据到 strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 strava 的步骤\n2. 把 gpx 文件全部拷贝到 GPX_OUT 中\n3. 在项目根目录下执行：\n\n```python\npython3(python) scripts/gpx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}\n```\n\n示例：\n\n```python\npython3(python) scripts/gpx_to_strava_sync.py xxx xxx xxx\n或\npython3(python) scripts/gpx_to_strava_sync.py xxx xxx xxx --all\n```\n\n3. 如果你已经上传过需要跳过判断增加参数 `--all`\n\n\u003c/details\u003e\n\n### Nike+Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e获取 \u003ccode\u003eNike Run Club\u003c/code\u003e 的跑步数据然后同步到 Strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 nike 和 strava 的步骤\n2. 在项目根目录下执行：\n\n```python\npython3(python) scripts/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresh_token}\n```\n\n示例：\n\n```python\npython3(python) scripts/nike_to_strava_sync.py eyJhbGciThiMTItNGIw******  xxx xxx xxx\n```\n\n\u003c/details\u003e\n\n### Garmin_to_Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e获取你的\u003ccode\u003e佳明\u003c/code\u003e 的跑步数据，然后同步到 Strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 garmin 和 strava 的步骤\n2. 在项目根目录下执行：\n\n```python\npython3(python) scripts/garmin_to_strava_sync.py  ${client_id} ${client_secret} ${strava_refresh_token} ${garmin_email} ${garmin_password} --is-cn\n```\n\n示例：\n\n```python\npython3(python) scripts/garmin_to_strava_sync.py  xxx xxx xxx xx xxx\n```\n\n\u003c/details\u003e\n\n### Strava_to_Garmin\n\n\u003cdetails\u003e\n\u003csummary\u003e获取你的\u003ccode\u003eStrava\u003c/code\u003e 的跑步数据然后同步到 Garmin\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 garmin 和 strava 的步骤，同时，还需要在 Github Actions secret 那新增 Strava 配置：`secrets.STRAVA_EMAIL`、`secrets.STRAVA_PASSWORD`\n2. 在项目根目录下执行：\n\n```python\npython3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}\n```\n\n如果你的佳明账号是中国区，执行如下的命令：\n\n```python\npython3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --is-cn\n```\n\n如果要在同步到Garmin的运动记录中添加Garmin设备信息，需要添加`--use_fake_garmin_device`参数，这将在同步的Garmin锻炼记录中添加一个Garmin设备（默认情况下为 `Garmin Forerunner 245`，您可以在`garmin_device_adaptor.py`中更改设备信息），运动记录中有了设备信息之后就可以同步到其他APP中，比如数字心动（攒上马积分）这类不能通过Apple Watch同步的APP，当然也可以同步到Keep，悦跑圈，咕咚等APP。\n\n\u003cimg width=\"830\" alt=\"image\" src=\"https://github.com/yihong0618/running_page/assets/8613196/b5076942-3133-4c89-ad66-a828211667dc\"\u003e\n\n\n最终执行的命令如下：\n\n```python\npython3(python) scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --use_fake_garmin_device\n```\n\n注意：**首次初始化的时候，如果你有大量的 strava 跑步数据，可能有些数据会上传失败，只需要多重试几次即可。**\n\n\u003c/details\u003e\n\n### Total Data Analysis\n\n\u003cdetails\u003e\n\u003csummary\u003e生成数据展示\u003c/summary\u003e\n\n- 生成数据展示 SVG\n- 展示效果：[点击查看](https://raw.githubusercontent.com/yihong0618/running_page/master/assets/github.svg)、[点击查看](https://raw.githubusercontent.com/yihong0618/running_page/28fa801e4e30f30af5ae3dc906bf085daa137936/assets/grid.svg)\n\n\u003e 注：感兴趣的同学可以改下方参数 (--special-distance 10 --special-distance2 20, 10km~20km 展示为 special-color1 20km 以上展示为 special-color2, --min-distance 10.0 用来筛选 10km 以上的)\n\n```\npython3(python) scripts/gen_svg.py --from-db --title \"${{ env.TITLE }}\" --type github --athlete \"${{ env.ATHLETE }}\" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github.svg --use-localtime --min-distance 0.5\n```\n\n```\npython3(python) scripts/gen_svg.py --from-db --title \"${{ env.TITLE_GRID }}\" --type grid --athlete \"${{ env.ATHLETE }}\"  --output assets/grid.svg --min-distance 10.0 --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime\n```\n\n生成年度环形数据\n\n```\npython3(python) scripts/gen_svg.py --from-db --type circular --use-localtime\n```\n\n更多展示效果参见：\n\u003chttps://github.com/flopp/GpxTrackPoster\u003e\n\n\u003c/details\u003e\n\n## server(recommend vercel)\n\n\u003cdetails\u003e\n\u003csummary\u003e使用 Vercel 部署\u003c/summary\u003e\n\n1. vercel 连接你的 GitHub repo\n\n![image](https://user-images.githubusercontent.com/15976103/94452465-2599b880-01e2-11eb-9538-582f0f46c421.png)\n\n2. import repo\n\n![image](https://user-images.githubusercontent.com/15976103/94452556-3f3b0000-01e2-11eb-97a2-3789c2d60766.png)\n\n2. 等待部署完毕\n3. 访问\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e 使用 Cloudflare 部署 \u003c/summary\u003e\n\u003cbr\u003e\n\n1. 在 `Pages` 中点击 `Create a project` 以连接到你的仓库\n\n2. 点击 `Begin setup` 后，修改项目的 `Build settings`。\n\n3. 在 `Framework preset` 中选择 `Gatsby` 框架。\n\n4. 向下滚动，点击 `Environment variables` 修改变量如下：\n\n   \u003e Variable name = `PYTHON_VERSION`, Value = `3.7`\n\n5. 点击 `Save and Deploy`，完成部署。\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e 部署到 GitHub Pages \u003c/summary\u003e\n\n1. 为 GitHub Actions 添加代码提交权限\n   访问仓库的 `Settings \u003e Actions \u003e General`页面，找到`Workflow permissions`的设置项，将选项配置为`Read and write permissions`，支持 CI 将运动数据更新后提交到仓库中。\n2. 更新配置并提交代码\n   1. 更新[./gatsby-config.js](./gatsby-config.js#L3)中的`siteMetadata`节点；\n      （按需）如果启用自定义域名模式或者变更 Fork 后的仓库名称，请变更`pathPrefix`的值。\n   2. 更新 GitHub CI 的配置 [.github/workflows/run_data_sync.yml](.github/workflows/run_data_sync.yml#L24) 中的配置；\n   3. （按需）如需使用自定义域名，可以修改 [.github/workflows/gh-pages.yml](.github/workflows/gh-pages.yml#L60) 中的 `fqdn`（默认已注释掉）\n   4. 在仓库的`Settings \u003e Secrets and variables \u003e Actions`页面添加对应服务的环境配置信息，参考不同平台[配置](#支持)。\n3. 同步数据并发布 GitHub Pages\n   1. 手动触发`Run Data Sync`的 Github Action 完成数据同步，完成后会自动触发`Publish GitHub Pages`的任务执行，等待执行完成；\n   2. 开通仓库 GitHub Pages 功能，选择`gh-pages`分支和`/(root)`目录。\n\n\u003c/details\u003e\n\n## GitHub Actions (Fork 的同学请一定不要忘了把 GitHub Token 改成自己的，否则会 push 到我的 repo 中，谢谢大家。)\n\n\u003cdetails\u003e\n\u003csummary\u003e修改 GitHub Actions Token\u003c/summary\u003e\n\nActions [源码](https://github.com/yihong0618/running_page/blob/master/.github/workflows/run_data_sync.yml)\n需要做如下步骤\n\n1. 更改成你的 app type 及 info\n   ![image](https://user-images.githubusercontent.com/15976103/94450124-73f98800-01df-11eb-9b3c-ac1a6224f46f.png)\n\n2. 在 repo Settings \u003e Secrets 中增加你的 secret (只添加你需要的即可)\n\n   ![image](https://user-images.githubusercontent.com/15976103/94450295-aacf9e00-01df-11eb-80b7-a92b9cd1461e.png)\n   我的 secret 如下\n   ![image](https://user-images.githubusercontent.com/15976103/94451037-8922e680-01e0-11eb-9bb9-729f0eadcdb7.png)\n\n\u003c/details\u003e\n\n## 把数据文件放在github cache中\n\n\u003cdetails\u003e\n\u003csummary\u003e把数据文件放在github cache中\u003c/summary\u003e\n\n`run_data_sync.yml`中的`SAVE_DATA_IN_GITHUB_CACHE`设置为`true`时，可以把脚本抓取和中间产生的数据文件放到github action cache中。这样可以让你的github commit历史和目录保持干净。\n\n如果你用github pages部署建议把这个值设置成`true`。\n\n如果你使用`Vervel`，需要在vercel后台进行下面几步操作：\n\n1. 在`General`的`Build \u0026 Development Settings`的Framework Preset选择Other，然后把override全部打开，命令行内容全部设置成空。\n\n  ![General](https://user-images.githubusercontent.com/413855/255507920-76932fb9-61d6-423e-92e2-2e92b5bbd432.png)\n\n2. 在Git模块中，`Production Branch`的Branch name填入`gh-pages`\n\n  ![Branch name](https://user-images.githubusercontent.com/413855/255508137-ef742815-8418-419a-86b4-6756ff68e1db.png)\n\n3. `run_data_sync.yml`中的`BUILD_GH_PAGES`设置为`true`\n\n\u003c/details\u003e\n\n# Fit 文件\n\n测试发现，不同厂商在写fit文件的时候有略微差异。\n\n已调试设备：\n\n- [x] 佳明手表\n- [x] 迈金码表\n\n如果发现自己的fit文件解析有问题。可以提issue。\n\n# TODO\n\n- [x] 完善这个文档\n- [x] 支持佳明，佳明中国\n- [x] 支持 keep\n- [ ] 支持苹果自带运动\n- [x] 支持 nike + strava\n- [x] 支持咕咚\n- [ ] 尝试支持小米运动\n- [x] 支持英语\n- [x] 完善代码\n- [x] 清理整个项目\n- [x] 完善前端代码\n- [x] better actions\n- [ ] tests\n- [ ] 支持不同的运动类型\n\n# 参与项目\n\n- 任何 Issues PR 均欢迎。\n- 可以提交 PR share 自己的 Running page 在 README 中。\n\n提交 PR 前：\n\n- 使用 black 对 Python 代码进行格式化。(`black .`)\n\n# 特别感谢\n\n- @[flopp](https://github.com/flopp) 特别棒的项目 [GpxTrackPoster](https://github.com/flopp/GpxTrackPoster)\n- @[danpalmer](https://github.com/danpalmer) 原始的 UI 设计\n- @[shaonianche](https://github.com/shaonianche) icon 设计及文档\n- @[geekplux](https://github.com/geekplux) 帮助及鼓励，重构了前端代码，学到了不少\n- @[ben-29](https://github.com/ben-29) 搞定了咕咚，和我一起搞定了悦跑圈，太厉害了\n- @[MFYDev](https://github.com/MFYDev) Wiki\n\n# 推荐的 Forks\n\n- @[gongzili456](https://github.com/gongzili456) for [摩托车骑行版本](https://github.com/gongzili456/running_page)\n- @[ben-29](https://github.com/ben-29) for [多种运动类型支持](https://github.com/ben-29/workouts_page)\n- @[geekplux](https://github.com/geekplux) for [多种运动类型支持](https://github.com/geekplux/activities)\n\n# 赞赏\n\n谢谢就够了\n\n# FAQ\n\n### Strava 100 每 15 分钟的请求，1000 每日限制\n\n\u003chttps://www.strava.com/settings/api\u003e\n\u003chttps://developers.strava.com/docs/#rate-limiting\u003e\n\n等待时间限制（这里是 strava 接口请求限制），不要关闭终端，这里会自动执行下一组上传数据\n\n```\nStrava API Rate Limit Exceeded. Retry after 100 seconds\nStrava API Rate Limit Timeout. Retry in 799.491622 seconds\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbpazy%2Fmy_running_page","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbpazy%2Fmy_running_page","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbpazy%2Fmy_running_page/lists"}