├── .gitignore ├── config.js ├── index.js ├── package.json ├── readMe.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | download -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cid: "195", 3 | _ga: "GA1.2.2060368404.1561339578", 4 | _gid: "GA1.2.2141692845.1561339578", 5 | GCID: "87358c7-b8c730b-fed8b15-550ad39", 6 | GCESS: 7 | "BAgBAwoEAAAAAAYEfvrKDwUEAAAAAAcEbf6b9gkBAQwBAQIECCcQXQMECCcQXQsCBAAEBAAvDQABBEgrGAA-" 8 | }; 9 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const Axios = require("axios"); 2 | const config = require("./config"); 3 | const shell = require("shelljs"); 4 | const fs = require("fs"); 5 | const path = require("path"); 6 | 7 | const axios = Axios.create({ 8 | headers: { 9 | Cookie: `_ga=${config._ga}; _gid=${config._gid}; GCID=${ 10 | config.GCID 11 | }; GCESS=${config.GCESS}`, 12 | "Content-Type": "application/json" 13 | } 14 | }); 15 | 16 | async function getList(cid) { 17 | let res = await axios 18 | .post( 19 | "https://time.geekbang.org/serv/v1/column/articles", 20 | { 21 | cid: cid, 22 | order: "earliest", 23 | prev: 0, 24 | sample: false, 25 | size: 50 26 | }, 27 | { 28 | headers: { 29 | Referer: `https://time.geekbang.org/course/intro/${cid}` 30 | } 31 | } 32 | ) 33 | .catch(err => console.log(err.response)); 34 | if (res && res.data.data.list && res.data.data.list.length > 0) { 35 | return res.data.data.list; 36 | } else { 37 | return []; 38 | } 39 | } 40 | 41 | async function download(item) { 42 | const localPath = `./download/${item.article_title.replace( 43 | /((\s|\|))/g, 44 | "_" 45 | )}.mp4`; 46 | return new Promise((resolve, reject) => { 47 | if (fs.existsSync(path.resolve(__dirname, localPath))) { 48 | resolve(0); 49 | } else { 50 | shell.exec( 51 | `ffmpeg -i ${item.video_media_map.hd.url} ${localPath}`, 52 | code => { 53 | if (code === 0) { 54 | resolve(0); 55 | } else { 56 | reject(); 57 | } 58 | } 59 | ); 60 | } 61 | }); 62 | } 63 | 64 | (async function() { 65 | !fs.existsSync(path.resolve(__dirname, "download")) && 66 | fs.mkdirSync(path.resolve(__dirname, "download")); 67 | const list = await getList(config.cid); 68 | for await (const item of list) { 69 | await download(item).catch(err => {}); 70 | } 71 | })(); 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geekbang-video-downloader-nodejs", 3 | "version": "1.0.0", 4 | "description": "极客时间会员视频下载器", 5 | "main": "index.js", 6 | "engines": { 7 | "node": ">=10" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [ 13 | "极客时间,视频下载" 14 | ], 15 | "author": "Xixi20160512", 16 | "license": "MIT", 17 | "dependencies": { 18 | "axios": "^0.19.0", 19 | "shelljs": "^0.8.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /readMe.md: -------------------------------------------------------------------------------- 1 | ⚠️:本代码已过时,不再适用当前的极客时间网站 2 | 3 | # 极客时间视频下载 4 | 5 | **注意:对于付费资源需要有相应权限才能下载。另外,代码只做学习交流用途,请勿用于非法情景。** 6 | 7 | ## 下载代码 8 | 9 | ```bash 10 | git clone git@github.com:Xixi20160512/geekbang-video-downloder-nodejs.git 11 | ``` 12 | 13 | ## 配置文件 14 | 15 | ```javascript 16 | module.exports = { 17 | cid: "", // 视频课程的id 18 | _ga: "", //cookie 19 | _gid: "", //cookie 20 | GCID: "", //cookie 21 | GCESS: "" //cookie 22 | }; 23 | ``` 24 | 25 | 比如我们打开一个课程的链接 26 | 27 | **https://time.geekbang.org/course/intro/95** 28 | 29 | 这里的 95 就是`cid`,另外的`cookie`内容是登录之后的 cookie,可以通过 chrome 插件 editthiscookie 进行查看。 30 | 31 | ## 依赖 32 | 33 | ### npm 34 | 35 | 进入根目录: 36 | 37 | ```bash 38 | npm install 39 | ``` 40 | 41 | ### ffmpeg 42 | 43 | 除了 npm 之外,代码执行还依赖`ffmpeg`包,这个工具的安装方式请自行搜索。 44 | 45 | 安装完之后验证: 46 | 47 | ```bash 48 | ffmpeg --version 49 | ``` 50 | 51 | 没有报错就是安装好了。 52 | 53 | ## 执行 54 | 55 | 在项目根路径执行: 56 | 57 | ```bash 58 | node index.js 59 | ``` 60 | 61 | ## 注意 62 | 63 | 项目需要依赖 node 10.0 以上版本 64 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | axios@^0.19.0: 6 | version "0.19.0" 7 | resolved "http://r.cnpmjs.org/axios/download/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" 8 | integrity sha1-jgm/89kSLhM/e4EByPvdAO09Krg= 9 | dependencies: 10 | follow-redirects "1.5.10" 11 | is-buffer "^2.0.2" 12 | 13 | balanced-match@^1.0.0: 14 | version "1.0.0" 15 | resolved "http://r.cnpmjs.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 16 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 17 | 18 | brace-expansion@^1.1.7: 19 | version "1.1.11" 20 | resolved "http://r.cnpmjs.org/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 21 | integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= 22 | dependencies: 23 | balanced-match "^1.0.0" 24 | concat-map "0.0.1" 25 | 26 | concat-map@0.0.1: 27 | version "0.0.1" 28 | resolved "http://r.cnpmjs.org/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 29 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 30 | 31 | debug@=3.1.0: 32 | version "3.1.0" 33 | resolved "http://r.cnpmjs.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 34 | integrity sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE= 35 | dependencies: 36 | ms "2.0.0" 37 | 38 | follow-redirects@1.5.10: 39 | version "1.5.10" 40 | resolved "http://r.cnpmjs.org/follow-redirects/download/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" 41 | integrity sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio= 42 | dependencies: 43 | debug "=3.1.0" 44 | 45 | fs.realpath@^1.0.0: 46 | version "1.0.0" 47 | resolved "http://r.cnpmjs.org/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 48 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 49 | 50 | glob@^7.0.0: 51 | version "7.1.4" 52 | resolved "http://r.cnpmjs.org/glob/download/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" 53 | integrity sha1-qmCKL2xXetNX4a5aXCbZqNGWklU= 54 | dependencies: 55 | fs.realpath "^1.0.0" 56 | inflight "^1.0.4" 57 | inherits "2" 58 | minimatch "^3.0.4" 59 | once "^1.3.0" 60 | path-is-absolute "^1.0.0" 61 | 62 | inflight@^1.0.4: 63 | version "1.0.6" 64 | resolved "http://r.cnpmjs.org/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 65 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 66 | dependencies: 67 | once "^1.3.0" 68 | wrappy "1" 69 | 70 | inherits@2: 71 | version "2.0.4" 72 | resolved "http://r.cnpmjs.org/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 73 | integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= 74 | 75 | interpret@^1.0.0: 76 | version "1.2.0" 77 | resolved "http://r.cnpmjs.org/interpret/download/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" 78 | integrity sha1-1QYaYiS+WOgIOYX1AU2EQ1lXYpY= 79 | 80 | is-buffer@^2.0.2: 81 | version "2.0.3" 82 | resolved "http://r.cnpmjs.org/is-buffer/download/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" 83 | integrity sha1-Ts8/z3ScvR5HJonhCaxmJhol5yU= 84 | 85 | minimatch@^3.0.4: 86 | version "3.0.4" 87 | resolved "http://r.cnpmjs.org/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 88 | integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= 89 | dependencies: 90 | brace-expansion "^1.1.7" 91 | 92 | ms@2.0.0: 93 | version "2.0.0" 94 | resolved "http://r.cnpmjs.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 95 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 96 | 97 | once@^1.3.0: 98 | version "1.4.0" 99 | resolved "http://r.cnpmjs.org/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 100 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 101 | dependencies: 102 | wrappy "1" 103 | 104 | path-is-absolute@^1.0.0: 105 | version "1.0.1" 106 | resolved "http://r.cnpmjs.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 107 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 108 | 109 | path-parse@^1.0.6: 110 | version "1.0.6" 111 | resolved "http://r.cnpmjs.org/path-parse/download/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 112 | integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw= 113 | 114 | rechoir@^0.6.2: 115 | version "0.6.2" 116 | resolved "http://r.cnpmjs.org/rechoir/download/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" 117 | integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= 118 | dependencies: 119 | resolve "^1.1.6" 120 | 121 | resolve@^1.1.6: 122 | version "1.11.1" 123 | resolved "http://r.cnpmjs.org/resolve/download/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" 124 | integrity sha1-6hDYEQN2mC/vV434/DC5rDCgej4= 125 | dependencies: 126 | path-parse "^1.0.6" 127 | 128 | shelljs@^0.8.3: 129 | version "0.8.3" 130 | resolved "http://r.cnpmjs.org/shelljs/download/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" 131 | integrity sha1-p/MxlSDr8J7oEnWyNorbKGZZsJc= 132 | dependencies: 133 | glob "^7.0.0" 134 | interpret "^1.0.0" 135 | rechoir "^0.6.2" 136 | 137 | wrappy@1: 138 | version "1.0.2" 139 | resolved "http://r.cnpmjs.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 140 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 141 | --------------------------------------------------------------------------------