核心概要
笔者是一名无缘211、985名校的大专生。虽为大专生但我的人生格言 “ 别向这个世界认输 因为你还有个牛逼的梦想 ” 不允许我只是一名普普通通的大专生。
年关已过 恢复正轨
笔者为了提升自身技术实力在 极客时间 用了一些银子买了门课程,但是没想到的是马上就要开学了,而 极客时间 的视频也只能在APP 内部缓存下载观看,很显然这个规则束缚了笔者。作为未来互联网的开发人员面对这种束缚当然是不能妥协的,于是就有了本专刊,本文章。
敢想敢做 不悔青春
下面我会以一名小白的角度来描述此次爬虫分析,当然了 笔者也是一名小白但只是比小白略强那么一些而已。
目标分析
爬虫分析
账户中心
POST https://account.geekbang.org/...
- 点击个人头像中的 用户名 会触发此接口的调用
- 通过分析此接口可以知道 极客时间 是以什么方案来解决 前端与后端交互安全认证的问题
- 当然有的小伙伴会想到使用
Session
来解决此问题,但是却忽略了Session
这个东西是存储在服务端的,而客户端存储的是SessionId
当浏览器关闭的时候这个SessionId
就会消失,而存储在服务端的Session
还会存在,这无疑是增加了服务端的压力,虽然在服务端做一些Session
的失效策略,但抛去这个问题不说,像这种大型的互联网项目服务端必然会是以集群的方式存在的,这个时候就需要考虑到Session
的共享问题或者是Session
的绑定问题等等。 - 使用
Cookie
Token
解决此问题,Cookie
Token
是只存储在客户端的文件,这相比于Session
来说是比较好的一种选择,因为这个时候服务端只需要考虑怎么解析和生成Cookie
Token
就可以了,而不需要考虑像Session
的共享问题等等。当然这也是 大型互联网项目中前后端交互安全认证问题解决方案中一种业界主流的解决方案 - 通过分析这个接口的
RequestHeaders
中可以发现,它采用的是Cookie
来封装一些 认证信息。当然了有懂Cookie
的小伙伴就有想法了,但是你要知道笔者也不是憨憨,所以这里的Cookie
肯定是过期的了。
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Length: 2
Content-Type: application/json
Cookie: _ga=GA1.2.1045223782.1639395871; LF_ID=1639395871969-5650567-1016048; GCID=5a7e11c-5fdc6e0-ec86384-1cc8de6; GRID=5a7e11c-5fdc6e0-ec86384-1cc8de6; MEIQIA_TRACK_ID=24ixuWXpI5WXM68hM1n4NdW4IrF; _gcl_au=1.1.2051684781.1644253524; _gid=GA1.2.302668339.1645078454; MEIQIA_VISIT_ID=25EJkkTDspp5EBAfgoPEKy7mcbm; GCESS=BgsCBgAEBAAvDQAKBAAAAAAGBPiLPOANAQEMAQEDBBwlDmIHBC7OZx8JAQEBCDVaLAAAAAAAAgQcJQ5iBQQAAAAACAED; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%222906677%22%2C%22first_id%22%3A%2217f073deb255c7-09d380380dbee5-f791539-1327104-17f073deb261016%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_landing_page%22%3A%22https%3A%2F%2Ftime.geekbang.org%2F%22%2C%22%24latest_utm_source%22%3A%22time_web%22%2C%22%24latest_utm_medium%22%3A%22menu%22%2C%22%24latest_utm_campaign%22%3A%22timewebmenu%22%2C%22%24latest_utm_content%22%3A%22menu%22%2C%22%24latest_utm_term%22%3A%22timewebmenu%22%7D%2C%22%24device_id%22%3A%2217db39bc70f775-0956fde004162-4343363-2073600-17db39bc710104d%22%7D; Hm_lvt_59c4ff31a9ee6263811b23eb921a5083=1645080295,1645094172,1645096912,1645164399; gksskpitn=13b506d9-98e1-440a-8777-1641eb71065d; _gat=1; Hm_lpvt_59c4ff31a9ee6263811b23eb921a5083=1645164463; SERVERID=1fa1f330efedec1559b3abbcb6e30f50|1645164465|1645164401; gk_process_ev={%22count%22:7%2C%22target%22:%22%22%2C%22utime%22:1645164473299}
Host: account.geekbang.org
Origin: https://account.geekbang.org
Referer: https://account.geekbang.org/dashboard/info
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
我的课程
POST https://time.geekbang.org/ser...
- 点击个人头像中的 我的课程 会触发此接口的调用
Request Body
desc
是否排序expice
失效枚举last_learn
最后一次学习learn_status
用户身份prev
当前页码size
分页大小
{
"desc": true,
"expire": 1,
"last_learn": 0,
"learn_status": 0,
"prev": 0,
"size": 20,
"sort": 1,
"type": "",
"with_learn_count": 1
}
Response Body
code
响应状态码data
数据信息list
课程的重要参数pid
课程IDarticles
这个应该是专刊信息或者是文档信息products
所有课程信息
error
错误信息
{
"code": 0,
"data": {
"has_expiring_product": false,
"learn_count": {
"total": 1
},
"list": [{
"pid": 739995653,
"ptype": "p35",
"aid": 0,
"ctime": 739995653,
"score": 2,
"is_expire": false,
"expire_time": 0,
"last_learned_time": 0
}],
"articles": [{...}],
"products": [{...}],
"page": {
"more": false,
"count": 0,
"score": 0,
"score0": 0
}
},
"error": {},
"extra": {
"cost": 739995653,
"request-id": "739995653"
}
}
- 请求此接口的时候是需要携带
Cookie
、Referer
等请求头参数。 - 分析此接口,别的不说 但 ResponseBody 中的
list
集合中的pid
属性肯定是能帮助笔者达到目的。 虽然里面有一些数据可以用到,但是这还不够详细,继续往下分析。
课程详情
POST https://time.geekbang.org/ser...
- 点击我的课程中的 具体课程 会触发此接口的调用
Request Body
cid
课程IDsize
显示多少课程列表条数prev
当前页码order
排序规则
{ "cid": "739995653", "size": 500, "prev": 0, "order": "earliest", "sample": false }
Response Body
error
错误信息data
list
课程列表信息 其中的id
是非常重要的,用来获取视频信息的page
分页数据
{ "error": [], "data": { "list": [{ "article_subtitle": "", "video_cover": "...", "id": 739995653, "had_viewed": true, "article_title": "張冲: 别向这个世界认输 因为你还有个牛逼的梦想", "article_cover": "", "video_media_map": { "sd": { "size": 739995653 }, "ld": { "size": 739995653 }, "hd": { "size": 739995653 } }, "is_video_preview": true, "article_summary": "張冲: 别向这个世界认输 因为你还有个牛逼的梦想", "column_had_sub": true, "is_finished": false, "subtitles": [], "include_audio": false, "article_could_preview": false, "chapter_id": "2457", "rate_percent": 1, "video_size": 739995653, "video_time_arr": { "m": "55", "s": "40", "h": "00" }, "video_id": "VX: ZhangchongSR0208", "column_sku": 739995653, "offline": { "file_name": "", "download_url": "" }, "video_time": "00:00:00", "is_required": true, "rate": {...}, "score": 739995653, "article_ctime": 739995653 }, {...}], "page": { "count": 739995653, "more": false } }, "code": 0 }
- 请求此接口的时候是需要携带
Cookie
、Referer
等请求头参数。 - 分析此接口,别的不说 但 ResponseBody 中的
list
集合中的id
属性肯定是能帮助笔者达到目的。 - 虽然里面有一些数据可以用到,但是这还不够详细,继续往下分析。.
观看视频
POST https://time.geekbang.org/ser...
- 观看 具体课程的视频 会触发此接口的调用
Request Body
id
课程列表的ID
{
"id": 739995653
}
Response Body
article_content
列表详情article_title
列表标题video_id
视频IDvideo_cover
视频封面product_id
课程IDid
列表IDhls_videos
HLS 视频播放地址ld
标清sd
高清hd
超清
{
"data": {
"article_content": "張冲: 别向这个世界认输 因为你还有个牛逼的梦想",
"article_title": "張冲: 别向这个世界认输 因为你还有个牛逼的梦想",
"video_id": "739995653",
"video_cover": "...",
"product_id": 739995653,
"id": 739995653,
"hls_videos": {
"sd": {
"url": "...?combat.m3u8",
"size": 739995653
},
"hd": {
"url": "...?combat.m3u8",
"size": 739995653
},
"ld": {
"url": "...?combat.m3u8",
"size": 739995653
}
},
}
}
- 请求此接口的时候是需要携带
Cookie
、Referer
等请求头参数。 - 分析此接口,最终我们得到了视频的地址,因为视频采用的是
HLS
协议的形式,因为小编的技术还没有发展到全栈开发,所以对这个东西了解的不是很深,只知道使用HLS
的方式会增加视频播放的流畅度,同时还可以根据网络情况来动态切换清晰度,所以它hls_videos
里面有三个清晰度可以选用。
下载视频
虽然拿到了M3U8 文件,但是真的可以下载吗?
- 下面只是
M3U8
文件的一部分,我们来看一下。 - 这个文件的地址是存储在
hls_videos
里面的,通常HLS
这个协议所携带的数据都是加密的 - 在看
M3U8
文件头中的EXT-X-KEY
属性,它所采用的加密算法是AES-128
- 虽然它加密了,但
M3U8
文件中也会有对应的解密文件,也就是URI
和VI
这两个属性。 - 现在市面上也有一些
M3U8
下载器、解析器,开源社区也有一些M3U8
下载器、解析器,这里就不过多解释了。 - 温馨提示:极客时间 播放视频所用的
M3U8
文件并不是我在上面所拿到的文件,它使用到了阿里云的HLS
服务(阿里云里面可以设置,使用标准的HLS 加密
或者使用阿里云私有加密
),很不幸的是 极客时间 使用的是阿里云私有加密
。所以如果直接对 极客时间 播放视频所用的M3U8
文件进行解析或下载的话,得到的视频是不能直接观看的。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="...?combat.key",VI=0x00000000000000000000000000000000
#EXTINF:10.000000,
413092fce65236f43dcb599457923728-sd-encrypt-stream-00001.ts
#EXTINF:10.000000,
413092fce65236f43dcb599457923728-sd-encrypt-stream-00002.ts
#EXTINF:10.000000,
413092fce65236f43dcb599457923728-sd-encrypt-stream-00003.ts
#EXTINF:10.000000,
413092fce65236f43dcb599457923728-sd-encrypt-stream-00004.ts
笔者留言
- 上面所展示的一些数据都不是真实的数据
- 以上是小编对极客时间爬虫分析的所有分享
- 注意: 爬虫要有度 从入门到放弃 人生不易要及时放弃
- 最后: 别向这个世界认输 因为你还有个牛逼的梦想
技术交流群 577729045 (快来和小编一起探讨交流吧)
以上内容如有冒犯 今致歉谢 恳望见原 请联系小编进行删除