|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "下载 raywenderlich.com 上的 iOS/Android/Unity 视频、源码" |
| 4 | +author: iosdevlog |
| 5 | +date: 2019-05-05 21:18:56 +0800 |
| 6 | +description: "" |
| 7 | +category: 教程 |
| 8 | +tags: [iOS, Android, Unity] |
| 9 | +--- |
| 10 | + |
| 11 | +## raywenderlich 简介 |
| 12 | + |
| 13 | +<https://www.raywenderlich.com> 对于 iOS 开发人员来说一定不陌生,这可能是 iOS 初级教程里面被推荐最多的网站了吧。 |
| 14 | + |
| 15 | +其实它不仅有 iOS 的开发教程,后面还出了 android 和 Unity 的开发教程。 |
| 16 | + |
| 17 | +教程简明实用,有原理介绍还有代码实现,直接可以看到实现效果,非常推荐大家也能写成像它上面的教程。 |
| 18 | + |
| 19 | +## [raywenderlich 官文介绍](https://help.raywenderlich.com/contact/) |
| 20 | + |
| 21 | +* 90kDAILY PAGEVIEWS |
| 22 | +* 2049ARTICLES |
| 23 | +* 2921VIDEOS & SCREENCASTS |
| 24 | +* 244TEAM MEMBERS |
| 25 | + |
| 26 | +raywenderlich.com is a community site focused on creating high quality programming tutorials. |
| 27 | + |
| 28 | +We pride ourselves on creating the highest-quality video courses, books, and written tutorials on the Internet. |
| 29 | + |
| 30 | +Every tutorial on our site goes through three rounds of editing before publication, to make sure each tutorial works 100%, is technically accurate, and provides comprehensive coverage of the topic. |
| 31 | + |
| 32 | +Thousands of developers and designers of all backgrounds, from all over the world, come to raywenderlich.com to teach and learn. |
| 33 | + |
| 34 | +We pay our authors and editor for all of their work, using the highest rates in the industry. |
| 35 | + |
| 36 | +Our goal is to create an environment where talented developers and teachers can make a living through their work, or advance their career by being recognized as an expert. |
| 37 | + |
| 38 | +## 下载 raywenderlich 资源 |
| 39 | + |
| 40 | +5 月 2 日收到 Ray Wenderlich <ray@raywenderlich.com> 的订阅邮件。 |
| 41 | + |
| 42 | + |
| 43 | + |
| 44 | +五一周末免费开放视频 3 天,太好了,为了以后也有时间观看,我决定把视频下载下来。 |
| 45 | + |
| 46 | +### youtube-dl |
| 47 | + |
| 48 | +最先找到 <https://github.com/ytdl-org/youtube-dl>,这上面提供多种视频下载。 |
| 49 | + |
| 50 | +代码 clone 下来一运行,报错!登录不成功。 |
| 51 | + |
| 52 | +这个难不倒我,使用 [Chrome ](https://chrome.google.com) 开发者工具,找到 `Header` 里面有一个 |
| 53 | + |
| 54 | +```js |
| 55 | +'Authorization': 'Token ..' |
| 56 | +``` |
| 57 | + |
| 58 | +打开 [Postman](https://www.getpostman.com),添加 `Authorization`。 |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | +`Hersers` 界面如下: |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +得到 `json` 文件: |
| 67 | + |
| 68 | +```json |
| 69 | +{ |
| 70 | + "video": { |
| 71 | + "id": 246, |
| 72 | + "name": "PDF Printing", |
| 73 | + "description": "Create a PDF file. We’ll create a budget report that you could then share.", |
| 74 | + "author_notes": "", |
| 75 | + "duration": 589, |
| 76 | + "pretty_duration": "9 minutes 49 seconds", |
| 77 | + "featured": false, |
| 78 | + "episode": 6, |
| 79 | + "format": "course", |
| 80 | + "language": null, |
| 81 | + "platform": null, |
| 82 | + "editor": null, |
| 83 | + "meta_description": null, |
| 84 | + "released_at": "2016-05-13T16:00:00.000Z", |
| 85 | + "difficulty": "intermediate", |
| 86 | + "created_at": "2016-08-04T02:56:51.175Z", |
| 87 | + "updated_at": "2019-04-28T10:01:25.399Z", |
| 88 | + "free": true, |
| 89 | + "attachments": [ |
| 90 | + { |
| 91 | + "id": 4605, |
| 92 | + "url": "https://files.betamax.raywenderlich.com/attachments/videos/246/CG-Int-MyList-06.png", |
| 93 | + "kind": "watchlist_artwork", |
| 94 | + "filename": "CG-Int-MyList-06.png", |
| 95 | + "retina": false |
| 96 | + }, |
| 97 | + { |
| 98 | + "id": 4606, |
| 99 | + "url": "https://files.betamax.raywenderlich.com/attachments/videos/246/CG-Int-MyList-06%402x.png", |
| 100 | + "kind": "watchlist_artwork", |
| 101 | + "filename": "CG-Int-MyList-06@2x.png", |
| 102 | + "retina": true |
| 103 | + }, |
| 104 | + { |
| 105 | + "id": 4607, |
| 106 | + "url": "https://files.betamax.raywenderlich.com/attachments/videos/246/CG-Int-VideoBanner-06.png", |
| 107 | + "kind": "video_banner", |
| 108 | + "filename": "CG-Int-VideoBanner-06.png", |
| 109 | + "retina": false |
| 110 | + }, |
| 111 | + { |
| 112 | + "id": 4608, |
| 113 | + "url": "https://files.betamax.raywenderlich.com/attachments/videos/246/CG-Int-VideoBanner-06%402x.png", |
| 114 | + "kind": "video_banner", |
| 115 | + "filename": "CG-Int-VideoBanner-06@2x.png", |
| 116 | + "retina": true |
| 117 | + }, |
| 118 | + { |
| 119 | + "id": 1736, |
| 120 | + "url": "https://files.betamax.raywenderlich.com/attachments/videos/246/005_IntCoreGraphics_PDF.zip", |
| 121 | + "kind": "materials", |
| 122 | + "filename": "005_IntCoreGraphics_PDF.zip", |
| 123 | + "retina": false |
| 124 | + } |
| 125 | + ], |
| 126 | + "authors": [ |
| 127 | + { |
| 128 | + "id": 25, |
| 129 | + "role": "instructor", |
| 130 | + "user": { |
| 131 | + "id": 9, |
| 132 | + "external_id": "8f5ca72a-11f3-11e6-b121-2380095a6428", |
| 133 | + "email": "caroline@archway.com.au", |
| 134 | + "username": "Caroline", |
| 135 | + "avatar_url": "https://www.gravatar.com/avatar/bfe2a965cd6136b9e2b485c959a57aff.jpg?d=https%3A%2F%2Fwolverine.raywenderlich.com%2Fv3-resources%2Fimages%2Fdefault-account-avatar_2x.png\u0026s=480", |
| 136 | + "name": "Caroline Begbie" |
| 137 | + } |
| 138 | + } |
| 139 | + ], |
| 140 | + "clips": [ |
| 141 | + { |
| 142 | + "id": 253, |
| 143 | + "provider_id": "164661205", |
| 144 | + "provider_url": "https://vimeo.com/164661205", |
| 145 | + "pretty_duration": "9m 49s", |
| 146 | + "clip_type": "primary_content", |
| 147 | + "attachments": [ |
| 148 | + { |
| 149 | + "id": 5470, |
| 150 | + "url": "https://files.betamax.raywenderlich.com/attachments/clips/253/164661205.vtt", |
| 151 | + "kind": "subtitles", |
| 152 | + "filename": "#164661205.vtt", |
| 153 | + "retina": false |
| 154 | + }, |
| 155 | + { |
| 156 | + "id": 1735, |
| 157 | + "url": "https://player.vimeo.com/external/164661205.m3u8?s=96740a5872b5272dc2e5b1a29af7b33a92e3739e\u0026oauth2_token_id=897711146", |
| 158 | + "kind": "stream", |
| 159 | + "filename": "#164661205", |
| 160 | + "retina": false |
| 161 | + }, |
| 162 | + { |
| 163 | + "id": 24274, |
| 164 | + "url": "https://player.vimeo.com/external/164661205.sd.mp4?s=dc9fad611715e5efa3e2544989877c3de083a2a5\u0026profile_id=165\u0026oauth2_token_id=897711146", |
| 165 | + "kind": "sd_video_file", |
| 166 | + "filename": "164661205.sd.mp4", |
| 167 | + "retina": false |
| 168 | + }, |
| 169 | + { |
| 170 | + "id": 24275, |
| 171 | + "url": "https://player.vimeo.com/external/164661205.hd.mp4?s=327799fd9b66832d7f7a53fa1a3d76cd8f9b902a\u0026profile_id=174\u0026oauth2_token_id=897711146", |
| 172 | + "kind": "hd_video_file", |
| 173 | + "filename": "164661205.hd.mp4", |
| 174 | + "retina": false |
| 175 | + } |
| 176 | + ] |
| 177 | + } |
| 178 | + ], |
| 179 | + "categories": [ |
| 180 | + { |
| 181 | + "id": 27, |
| 182 | + "name": "carolus: Graphics \u0026 Animation" |
| 183 | + }, |
| 184 | + { |
| 185 | + "id": 42, |
| 186 | + "name": "domain: ios" |
| 187 | + }, |
| 188 | + { |
| 189 | + "id": 6, |
| 190 | + "name": "Graphics" |
| 191 | + } |
| 192 | + ] |
| 193 | + } |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +当然现在已经不行了。 |
| 198 | + |
| 199 | +```json |
| 200 | +{ |
| 201 | + "error": "video not available" |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +youtube-dl 是可以登录 raywenderlich,可是又报 `Vimeo` 登录错误。 |
| 206 | + |
| 207 | +叹! |
| 208 | + |
| 209 | +另辟蹊径吧,我们来解析一下 `json` 文件吧。我发现 |
| 210 | + |
| 211 | +```son |
| 212 | +{ |
| 213 | + "video": { |
| 214 | + "name": "PDF Printing", |
| 215 | + "clips": [ |
| 216 | + { |
| 217 | + "attachments": [ |
| 218 | + { |
| 219 | + "id": 1735, |
| 220 | + "url": "https://player.vimeo.com/external/164661205.m3u8?s=96740a5872b5272dc2e5b1a29af7b33a92e3739e\u0026oauth2_token_id=897711146", |
| 221 | + "kind": "stream", |
| 222 | + "filename": "#164661205", |
| 223 | + "retina": false |
| 224 | + } |
| 225 | + ] |
| 226 | + } |
| 227 | + ] |
| 228 | + } |
| 229 | +} |
| 230 | +``` |
| 231 | + |
| 232 | +找到 ` "kind": "stream"` 内容,使用 [FFmpeg](https://ffmpeg.org) 下载。 |
| 233 | + |
| 234 | +```sh |
| 235 | +$ ffmpeg -i "https://player.vimeo.com/external/164661205.m3u8?s=96740a5872b5272dc2e5b1a29af7b33a92e3739e\u0026oauth2_token_id=897711146" "PDF Printing.mp4" |
| 236 | +``` |
| 237 | + |
| 238 | +好的,可以下载。但是这个下载速度也实在是太慢了吧! |
| 239 | + |
| 240 | +放我的服务器上面下载,结果 *FFmpeg* 报 `CPU` 错误,我... |
| 241 | + |
| 242 | +我在 google 上面找啊找,找啊找,还是找不着解决方法。 |
| 243 | + |
| 244 | +实在不行,我多开几个终端慢慢下吧。 |
| 245 | + |
| 246 | +### 下载资源(PDF,源码) |
| 247 | + |
| 248 | +通过解析上面的 `json` 文件,看到还有附件呢,正好前几天有人在 [B站](https://www.bilibili.com/video/av11086645) 问我要 [Ray Wenderlich Video Tutorial - Introducing Custom Controls](https://www.bilibili.com/video/av11086645) 的源码,我把源码也下载下来吧。 |
| 249 | + |
| 250 | +这个实现比较简单,直接放出源码。 |
| 251 | + |
| 252 | +```python |
| 253 | +import requests |
| 254 | +from bs4 import BeautifulSoup |
| 255 | +import os |
| 256 | + |
| 257 | +base_url = 'https://www.raywenderlich.com' |
| 258 | + |
| 259 | +headers = { |
| 260 | + "Accept" : "application/json, text/javascript, */*; q=0.01", |
| 261 | + "Authorization" : "Bearer xxx", |
| 262 | + "Origin" : "https://www.raywenderlich.com", |
| 263 | + "Referer" : "https://www.raywenderlich.com/", |
| 264 | + "User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36", |
| 265 | + "X-CSRF-Token" : "qnaS...", |
| 266 | + "X-Requested-With" : "XMLHttpRequest", |
| 267 | + } |
| 268 | + |
| 269 | +def download(url): |
| 270 | + r = requests.get(url, headers=headers) |
| 271 | + |
| 272 | + result = raywenderlich_from_dict(r.json()) |
| 273 | + name = result.video.name.replace('&', '').replace(':', '').replace('?', '') |
| 274 | + attachments = result.video.attachments |
| 275 | + |
| 276 | + _id = result.video.id |
| 277 | + _name = result.video.name.replace('&', '').replace(':', '').replace('?', '') |
| 278 | + |
| 279 | + for attachment in attachments: |
| 280 | + filename = attachment.filename |
| 281 | + url = attachment.url |
| 282 | + cmd = 'wget -O "%s. %s %s" %s' % (_id, _name, filename, url) |
| 283 | + os.system(cmd.encode('utf-8')) |
| 284 | + |
| 285 | +if __name__ == '__main__': |
| 286 | + for i in range(2789): |
| 287 | + url = 'https://videos.raywenderlich.com/api/v1/videos/%s.json' % I |
| 288 | + print(url) |
| 289 | + try: |
| 290 | + download(url) |
| 291 | + except: |
| 292 | + print(i) |
| 293 | +``` |
| 294 | + |
| 295 | +这样就可以下载所有附件了。 |
| 296 | + |
| 297 | +### 再战视频下载 |
| 298 | + |
| 299 | +第二天我又从服务器运行 `youtube-dl`,居然不报错了,太棒了,赶紧下载。 |
| 300 | + |
| 301 | +不过 `youtube-dl` 只能下 `youtube-dl` 里面的 **Video Course** 系列视频,而不能下载 **Screencast** 单个视频。原来 `_VALID_URL` 是不匹配,而且里面的内容也不一样。 |
| 302 | + |
| 303 | +是可忍,孰不可忍。 |
| 304 | + |
| 305 | +#### 直接动手改代码 |
| 306 | + |
| 307 | +```sh |
| 308 | +$ git checkout -b raywenderlich_screencast |
| 309 | +``` |
| 310 | + |
| 311 | +修改 `raywenderlich.md`: |
| 312 | + |
| 313 | +```python |
| 314 | +class RayWenderlichIE(InfoExtractor): |
| 315 | + _VALID_URL = r'''(?x) |
| 316 | + https?:// |
| 317 | + (?: |
| 318 | + videos\.raywenderlich\.com/courses| |
| 319 | + (?:www\.)?raywenderlich\.com |
| 320 | + )/ |
| 321 | + (?P<id>[^/]+) |
| 322 | +``` |
| 323 | +
|
| 324 | +实现内容比之前更简单了,直接从 *thumbnail* 中找到 *video_id* 就好了,不过 *thumbnail* 有时候是空的,好说,正则表达式大法伺候。 |
| 325 | +
|
| 326 | +于是又安心的睡觉去了。 |
| 327 | +
|
| 328 | +**嘀嘀嘀!原来是磁盘满了,再哭。** |
| 329 | +
|
| 330 | +好吧,我一咬牙,一跺脚,再买一个磁盘大点的服务器(就买一个月吧,实在是没钱了)。 |
| 331 | +
|
| 332 | +慢慢下载去吧。 |
| 333 | +
|
| 334 | +嘘。嘘。嘘。。。 |
| 335 | +
|
| 336 | +第二天磁盘又满了,赶紧下载 [BaiduPCS-Go](https://github.com/iikira/BaiduPCS-Go)。 |
| 337 | +
|
| 338 | +快点上传啊,我求求你了。结果没用,好的时候有好几 M 的速度,一会儿又只剩下几 k。 |
| 339 | +
|
| 340 | +最后结果:共有 2K 多的视频,我下载了 1K 多的视频。 |
| 341 | +
|
| 342 | +## 总结 |
| 343 | +
|
| 344 | +1. 时间真的比金钱重要。 |
| 345 | +1. 提前做好准备。 |
| 346 | +
|
| 347 | +关注我的公众号,AI开发日志(AIDevLog) / iOS开发日志(iOSDevLog)。 |
| 348 | +
|
| 349 | + |
| 350 | +
|
| 351 | + |
| 352 | +
|
| 353 | +有需要资源的可以联系我,直接共享容易封,我也在慢慢上传 [B站](https://www.bilibili.com/video/av11086645)。 |
| 354 | +
|
| 355 | +**有条件的请去官网 <https://www.raywenderlich.com> 观看** |
0 commit comments