使用天翼网盘搭建免费的视频播放网站

各类的网盘索引程序有很多了,笔者尝试了PanIndex,最后使用的是JustList,也经历了一翻踩坑,遂总结如下。

使用网盘索引程序,再搭配上免费的应用云或者函数计算,就可以制作一个免费的视频播放网站啦。当然,视频播放站点只是一个引子,做做静态博客之类的也不错。

方案一:heroku 方案

heroku不多说了,国外免费的PaaS平台,可以免费部署一个应用。使用heroku托管JustList的主要步骤如下:

  1. 新建一个空的heroku应用,起个名字myappheroku
  2. 将JustList复制到本地
git clone https://github.com/txperl/JustList
  1. 适配heroku启动环境

修改步骤2得到的JustList文件夹中的内容:

  • requirements.txt 添加一行 gunicorn
  • 新建文件Procfile 内容为 web: gunicorn main:app
  • 适配入口函数,对main.py做以下修改:
# ...
rootPath = os.path.dirname(os.path.abspath(__file__)) + "/" # 修改rootPath,避免gunicorn读取到错误的rootPath无法启动:boolean型变量无法取下标
# ...
# if __name__ == '__main__': # 移动到下面,避免gunicorn启动时Altfe未初始化的问题:获取列表的接口未正常注册
# Altfe 框架初始化
classRoot.setENV("rootPath", rootPath)
classRoot.setENV("rootPathFrozen", rootPathFrozen)
bridge.bridgeInit().run(hint=True)
# 调整日志等级
logging.getLogger("werkzeug").setLevel(logging.ERROR)

if __name__ == '__main__':
    # 启动
    # app.run(host="127.0.0.1", port=5000, debug=True, threaded=True, use_reloader=False)
    http_server = WSGIServer(("0.0.0.0", 5000), app)
    http_server.serve_forever()

main.py的修改主要有两处:一是修改了rootPath,二是移动了if __name__ == '__main__'语句。分别解决了boolean型变量无法取下标获取文件列表的接口未注册的问题。

  1. 修改帐号配置

帐号配置在app/config/cloud189.yml路径下,修改为自己的天翼云盘帐号密码即可。

⚠注意事项:请不要将自己的帐号密码明文写在公开的仓库里面。可以采用本地存储通过heroku cli工具上传至heroku。如果使用GitHub仓库,请使用私有仓库,或从环境变量等中读取帐号密码。

如果采用环境变量读取帐号密码,请修改app/lib/core/cloud189/main.py

# ...
import os
# ...

            self.api[u] = cloud189.cloud189(
                os.environ.get(self.conf["accounts"][u][0]), os.environ.get(self.conf["accounts"][u][1])
            )
#...

同时,需要配置heroku的环境变量:

heroku config:set USER189=USER --app myappheroku
heroku config:set PASS189=PASS --app myappheroku

myappheroku应当与你的heroku应用名称相同,USER189PASS189是填写在cloud189.yml的信息,USERPASS是真实的帐号密码。

  1. 部署
heroku login
heroku git:clone -a myappheroku
cd myappheroku

然后将Justlist文件夹中的内容全部(除隐藏文件夹.git外)复制到myappheroku文件夹,之后:

git add .
git commit -am "make it better"
git push heroku master

就可以愉快地玩耍了~

方案二:阿里云 函数计算 方案

为什么采用阿里云的函数计算,不采用某讯云呢?因为某讯云的函数计算是收费的,而阿里云的免费额度对个人来说基本够用。注意:需要使用的是阿里云-函数计算 FC-应用不是阿里云-Serverless应用引擎 SAE的应用。这两者的区别还是蛮大的。重要的是,SAE的所有内容都是计费的,而函数计算 FC-的应用在轻量使用下仅出网流量计费。对网盘索引类程序而言,视频和图片等的流量走的都是网盘服务商(例如天翼云盘),自身站点的流量主要是一个静态网页和几个API接口,流量很少,这点流量对于函数计算来说完全是挠痒痒。

  1. 创建应用

一开始阿里云会让你关联GitHub,关联之后创建应用即可:函数计算 FC (aliyun.com)https://fcnext.console.aliyun.com/applications/create

JustList采用的是Flask框架,打开链接后,搜索框搜索flask,使用该模板(立即创建)。这里推荐将该应用与Github的一个私有仓库建立关联,这样每次Push之后,阿里云会自动重新部署应用。

将私有仓库复制到本地后,之后开始修改大改:

  1. 修改帐号配置

仓库的目录结构

仓库的目录结构如上图所示,需要将JustList中的内容复制到code文件夹下。

帐号配置在code/app/config/cloud189.yml路径下,修改为自己的天翼云盘帐号密码即可。

⚠注意事项:阿里云在部署应用时提供了可视化的环境变量配置,但是自动将环境变量穿透Docker内部。这就导致了python代码os.environ.get一度获取不到环境变量。如果python代码需要获取环境变量,需要Dockerfile再传递一次(我要这可视化配置有何用)

我一开始是使用环境变量设置的帐号密码,结果一直无法获取天翼网盘的token,最后才找到原因。这里推荐大家用私有仓库,直接写帐号密码,这样比较方便,还可以避免许多问题。

  1. 适配函数计算环境

之后,按照模板要求,需要将code/main.py重命名为code/index.py,并将端口修改为9000

index.py做以下修改:

# ...
rootPath = os.path.dirname(os.path.abspath(__file__)) + "/" # 修改rootPath
# ...
# if __name__ == '__main__': # 这个index.py是入口,所以这一行动不动都行
# Altfe 框架初始化
classRoot.setENV("rootPath", rootPath)
classRoot.setENV("rootPathFrozen", rootPathFrozen)
bridge.bridgeInit().run(hint=True)
# 调整日志等级
logging.getLogger("werkzeug").setLevel(logging.ERROR)

if __name__ == '__main__':
    # 启动
    http_server = WSGIServer(("0.0.0.0", 9000), app)
    http_server.serve_forever()

index.py的修改主要有两处:一是修改了rootPath,二是修改了端口号。

git push之后,阿里云会自动重新部署。打开函数计算的网页,发现函数计算已经开始生效了,可以看到JustList的前端网页,但前端显示的列表内容是空的。经过一番调试之后,发现获取文件列表的接口返回了404。和先前状态码为200,但返回内容为方法不存在不同,这次是直接返回了404状态码。

  1. 优化触发器

经过仔细排查,终于找到了原因。阿里云函数计算的Flask应用模板默认的触发器设置使得函数仅在GET请求下触发,导致JustList的POST接口全部404。我在调试的时候一度找不到问题所在。(而且,这个函数计算 FC-应用调试起来挺费劲的,缺少简单的可视化日志,只有冗长的日志配置,关键还要收费。)

对仓库下面的几个.yaml文件做以下修改:

            methods:
              - GET
              - POST # 新增

当我以为,到这里,已经万事俱备,该晴天大好的时候。然而并不是。果然是我太天真了。

  1. 移除定时函数

改好了之后,获取全部文件列表的POST接口终于不404了,也不是200+方法不存在,而是返回了一个空对象{}。真是奇怪了。经过深度调试(十几次commit),最终,终于找到了问题所在。函数计算和heroku不同,函数计算是由触发器动态触发,并动态计费的,而heroku是常驻后台的。这里和Serverless应用引擎 SAE也不一样,SAE只要不停止应用,就会一直计费。

可能是出于设计范式的原因,函数计算 FC的单个函数不允许同时执行多个线程(未找到相关文档)。因而,code/app/lib/core/cloud189/main.py中的代码未正常执行:

        t = threading.Timer(0, self.__childth_check)
        t.setDaemon(True)
        t.start()
        print('Are you OK?')

    def __childth_check(self):
        print("I'm okay*1")
        while True:
            print("I'm okay*2")
            tim = time.time()
            try:
                print("I'm okay*3")
                self.__update_token(tim)
                if tim > self.listOutdated:
                    self.load_list()
            except Exception as e:
                self.STATIC.localMsger.error(e)
            time.sleep(self.conf["sys_checkTime"])

上面的代码中,可以得到Are you OK?,但得不到任何一个I'm okay

临时的解决办法:

        self.__childth_check()
        # t = threading.Timer(0, self.__childth_check)
        # t.setDaemon(True)
        # t.start()
        print('Are you okay?')

    def __childth_check(self):
        tim = time.time()
        try:
            self.__update_token(tim)
            if tim > self.listOutdated:
                self.load_list()
        except Exception as e:
            self.STATIC.localMsger.error(e)

这样每次请求后端都会刷新token,由于前端有缓存,因而并不会每次都请求所有文件列表的接口,所以代价并不大。更优雅的实现应当是将这个定时任务交给一个定时函数,并在多个函数间共享token(日后再议)

至此,终于Opps了~

成品如下图:


一个视频

你可能感兴趣的:(使用天翼网盘搭建免费的视频播放网站)