Skip to content
This repository has been archived by the owner on Aug 22, 2024. It is now read-only.

如果url链接无效好像就会导致报错 #6

Closed
ZJC-GH opened this issue Apr 3, 2024 · 1 comment
Closed

如果url链接无效好像就会导致报错 #6

ZJC-GH opened this issue Apr 3, 2024 · 1 comment

Comments

@ZJC-GH
Copy link
Contributor

ZJC-GH commented Apr 3, 2024

当vga视频不存在的时候报错了,好像是url链接无效?

报错举例(延河课堂网站上就没有vga的视频,但是好像程序能读到链接?):
python main.py 44666 -L 4 --skip

解决方案

改变yanhekt.py文件,将原有的download类中的代码进行替换,以解决无效URL和路径不存在的问题(好像不能直接传单个.py文件,我就把整个代码放进来好了):

'''
Project      :
FilePath     : \OPENSOURCE\yanhekt.py
Descripttion :
Author       : GDDG08
Date         : 2022-11-08 02:07:44
LastEditors  : GDDG08
LastEditTime : 2024-04-03 16:03:17
'''
import os
import requests

from m3u8dl import M3u8Download

headers = {
    'Origin': 'https://www.yanhekt.cn',
    "xdomain-client": "web_user",
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26'
}


class YanHeKT():
    def __init__(self, _courseID, _all=False, _list=None, _range=None, _dual=True, _vga=False, _video=False, _skip=False, _dir='./',  _max_workers=32) -> None:
        self.courseID = _courseID
        self.lessonList = None
        self.courseInfo = None

        self.updateArgs(_all, _list, _range, _dual, _vga, _video, _skip, _dir, _max_workers)

    def updateArgs(self, _all=False, _list=None, _range=None, _dual=True, _vga=False, _video=False, _skip=False, _dir='./',  _max_workers=32):
        self.all = _all
        self.list = _list
        self.range = _range
        self.dual = _dual
        self.vga = _vga
        self.video = _video
        self.skip = _skip
        self.dir = _dir
        self.max_workers = _max_workers

    def getCourseInfo(self):
        print("----Getting Course Information----")

        rqt_course = requests.get(f'https://cbiz.yanhekt.cn/v1/course?id={self.courseID}&with_professor_badges=true', headers=headers)
        courseInfo = rqt_course.json()['data']

        print(courseInfo['name_zh'])

        print("-----Getting Lesson List-----")
        rqt_list = requests.get(f'https://cbiz.yanhekt.cn/v2/course/session/list?course_id={self.courseID}', headers=headers)
        lessonList = rqt_list.json()['data']

        for i, lesson in enumerate(lessonList):
            print(f"[{i}] ", lesson['title'])

        self.courseInfo = courseInfo
        self.lessonList = lessonList
        return courseInfo, lessonList

    def download(self, callback=None, callback_prog=None):
        if not self.lessonList or not self.courseInfo:
            self.getCourseInfo()

        print("------Start Downloading------")

        selectList = []
        if self.all:
            selectList = list(range(len(self.lessonList)))
        elif self.list:
            selectList = self.list
        elif self.range:
            selectList += list(range(self.range[0][0], self.range[0][1]))
        else:
            print("[Error] No lesson selected in args.")
            print("Please use -A/--all, -L/--list, or -R/--range to select lessons.")
            print("Example:")
            print(f"\tpython main.py {self.courseID} --all")
            print(f"\tpython main.py {self.courseID} --list 0 2 4")
            print(f"\tpython main.py {self.courseID} --range 3 5")

            if callback:
                callback(False)
            return

        courseFullName = '-'.join([str(self.courseID), self.courseInfo['name_zh'], self.courseInfo['professors'][0]['name']])
        dirName = os.path.join(self.dir, courseFullName)

        if not os.path.exists(dirName):
            os.makedirs(dirName)

        for i in selectList:
            video = self.lessonList[i]
            fileName = video['title'].replace("/", "-")  # 防止文件名中的/导致路径错误

            print(f"Downloading {fileName} --->")

            videos = video['videos'][0]
            # 下载投影录屏
            if self.vga or self.dual:
                vga_url = videos.get('vga')
                if vga_url:
                    vga_url = self.validate_url(vga_url)
                    vga_path = f"{dirName}/{fileName}-VGA.mp4"
                    self.download_video(vga_url, vga_path, "VGA", callback_prog)

            # 下载视频
            if self.video or self.dual:
                video_url = videos.get('main')
                if video_url:
                    video_url = self.validate_url(video_url)
                    video_path = f"{dirName}/{fileName}-Video.mp4"
                    self.download_video(video_url, video_path, "Video", callback_prog)

        if callback:
            callback(True)

    def validate_url(self, url):
        if not url.startswith(('http://', 'https://')):
            return f'https://{url.lstrip("/")}'  # 确保URL以正确的协议开头
        return url

    def download_video(self, url, path, video_type, callback_prog):
        """辅助函数来处理视频下载。"""
        if self.skip and os.path.exists(path):
            print(f"{video_type} seems already done. Skipping...")
            return
        print(f"{video_type} -->")
        try:
            M3u8Download(url, os.path.dirname(path), os.path.basename(path), max_workers=self.max_workers,
                         callback_progress=callback_prog)
        except Exception as e:
            print(f"Failed to download {video_type} video. Error: {e}")

        return


if __name__ == '__main__':
    # main()
    # yanhekt = YanHeKT(12345, _all=True, _dir='./')
    # yanhekt.download(callback_prog=progressPrint)
    pass

代码变动说明

URL 验证:增加了一个方法 validate_url 以确保URL以 "http://" 或 "https://" 开头。这个方法同样处理以 "//" 开头的协议相对URL,通过添加 "https:" 作为协议方案。

路径检查:download_video 方法中增加了对已存在文件的检查。

错误处理:在 download_video 方法中为 M3u8Download 函数调用增加了 try-except 块,用于处理下载过程中可能发生的任何异常,并打印特定于视频类型 (VGA 或 视频) 的错误信息。

代码模块化:通过将下载逻辑移至 download_video,代码更加模块化,便于维护和调试。

@GDDG08
Copy link
Owner

GDDG08 commented Apr 3, 2024

2.3.4已修复

@GDDG08 GDDG08 closed this as completed Apr 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants