def get_content(self, section_id): """ 获取章节内容 :params section_id: 章节url :params u: 章节url """ resp = json.loads( network_connect( self.section_api_url.format(self.class_id, section_id)).text) # {'code': 403, 'data': [], 'msg': '哎呀,课程内容丢失了'} code = resp.get("code", None) if code == None or code != 200: return False else: content_data = resp.get("data", []) if content_data == []: return False else: nodes = content_data["nodes"] # 原生html代码 text_list = [ node["content"] if node["content_type"] == 1 else node["content"]["content"] if node["content_type"] == 3 else "" for node in nodes ] # video_id列表 video_id_list = [ node["content"]["id"] for node in nodes if node["content_type"] == 2 ] return text_list, video_id_list
def get_stage_data(self): """ 获取每个章节的数据 :params class_id:课程id :return :课程data [{'stage_id': 1899, 'stage_name': '课前内容'},...] """ class_id = self.class_id res = json.loads( network_connect(self.class_api_url.format(class_id)).text) code = res.get("code", None) if code == None or code == 0: return False else: study_stage_data = res.get("data", []) if study_stage_data == []: return False else: self.class_name = study_stage_data["class_name"] stage_data = [{ "stage_id": i["stage_id"], "stage_name": i["stage_name"] } for i in study_stage_data["study_stage"] if i["is_lock"] == 0] return stage_data
def get_m3u8_key(self): with open(self.m3u8_path, "r", encoding="utf8") as f: for i in f.readlines(): if "EXT-X-KEY" in i: key_url = i.split('URI="')[1].split('"')[0] if key_url != self.key_url: return self.key_url, network_connect(key_url).content
def get_ts(self): with open(self.m3u8_path, "r", encoding="utf8") as f: r = f.readlines() for i in range(len(r)): if "#EXTINF" in r[i]: ts_url = r[i + 1].replace("\n", "") ts_name = r[i + 1].replace("\n", "").split("?")[0].split("/")[-1] print("\rTS文件下载中...({}/{}){}".format(i, len(r), ts_name), end="") self.ts_list.append(ts_name) resp = network_connect(ts_url).content self.down_ts(ts_name, resp)
def main(self, video_path, audio_matser_url): """ :params video_path:视频存储路径.H:\test.mp4 :params audio_matser_url:视频地址 """ # audio_matser_url-media_rates_url # 视频地址-码率链接列表(down)-高码率m3u8(down)-get加密key-下载ts(down)-合并ts # 存在则跳过SV流程 if os.path.exists(video_path): print(video_path, "已存在") return self.ts_list = [] self.sv_path = video_path.rsplit("\\", 1)[0] video_id = audio_matser_url.split("video_id=")[-1] media_rates_url = self.get_m3u8_url(audio_matser_url) if media_rates_url == None: print("获取media_rates_url失败 audio_matser_url: ", audio_matser_url) return self.high_rate_m3u8_url = self.parse_rate(media_rates_url) if self.high_rate_m3u8_url == "": print("高码率视频m3u8链接获取失败 audio_matser_url: ", audio_matser_url) return # 高码率m3u8文件名称 self.high_rate_m3u8_name = self.high_rate_m3u8_url.split("?")[0].split( "/")[-1] # 以m3u8文件名前缀创建临时目录 self.m3u8_work_path = folder(self.sv_path, video_id) # 高码率m3u8文件存储路径 self.m3u8_path = os.path.join(self.m3u8_work_path, self.high_rate_m3u8_name) # 下载高码率m3u8文件 self.down(self.m3u8_path, network_connect(self.high_rate_m3u8_url).content) self.key_url, self.key = self.get_m3u8_key() if self.key == None: print("m3u8Key获取失败: ", self.key) return self.cryptor = AES.new(self.key, AES.MODE_CBC, self.key) self.get_ts() self.ts2mp4(video_path) # sjk = SJK_VIDEO() # sjk.main(r"G:\python_code\test.mp4","https://service.sanjieke.cn/video/master/auth?video_id=xxxxx&class_id=2xxxx")
def parse_rate(self, media_rates_url): media_m3u8_name = media_rates_url.split("?")[0].split("/")[-1] media_m3u8_path = os.path.join(self.sv_path, media_m3u8_name) self.down(media_m3u8_path, network_connect(media_rates_url).content) high_rate_m3u8_url = "" with open(media_m3u8_path, "r", encoding="utf8") as f: r = f.readlines() for i in range(len(r)): if "#EXT-X-STREAM-INF" in r[i]: # 只取第一个高码率的地址 high_rate_m3u8_url = r[i + 1].replace("\n", "") break # 删除多码率列表文件 os.remove(media_m3u8_path) return high_rate_m3u8_url
def get_section_data(self, stage_id): """ 获取每个card里的文章数据 :parmas stage_id: 章节id :return: 章节数据, """ u = self.stage_api_url.format(self.class_id, stage_id) res = json.loads(network_connect(u).text) code = res.get("code", None) if code == None or code == 0: return False else: study_section_data = res.get("data", []) if study_section_data == []: return False else: section_data = [{ "card_name": i["card_name"], "section_id": j["section_id"], "section_name": j["section_name"] } for i in study_section_data["nodes"] for j in i["children"]] return section_data
def get_m3u8_url(self, audio_matser_url): resp = json.loads(network_connect(audio_matser_url).text) if resp.get("code", None) == 200: return resp["data"]["url"] else: return None