Browse Source

add Dockerfile and update todo

liuyuqi-dellpc 1 year ago
parent
commit
997431fd0f

+ 26 - 0
.dockerignore

@@ -0,0 +1,26 @@
+**/__pycache__
+**/.venv
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/bin
+**/charts
+**/docker-compose*
+**/compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+README.md

+ 0 - 0
.github/workflows/main.yml


+ 66 - 0
.github/workflows/release.yml

@@ -0,0 +1,66 @@
+name: auto CI
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+    
+jobs:
+  build:
+    strategy:
+      matrix:
+        os: [windows-latest]
+        include:
+        - os: ubuntu-latest
+          path: ~/.cache/pip
+        - os: macos-latest
+          path: ~/Library/Caches/pip
+        - os: windows-latest
+          path: ~\AppData\Local\pip\Cache
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+        
+      - name: Set up Python 3.8
+        id: setup-python
+        uses: actions/setup-python@v2
+        with:
+          python-version: 3.8
+
+      - uses: actions/cache@v2
+        with:
+          path: ${{ matrix.path }}
+          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+          restore-keys: |
+            ${{ runner.os }}-pip-
+
+      - uses: actions/cache@v2
+        with:
+          path: ~/.local/share/virtualenvs
+          key: ${{ runner.os }}-python-${{ steps.setup-python.outputs.python-version }}-pipenv-${{ hashFiles('Pipfile.lock') }}
+        
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+
+      - name: build exe
+        run: |
+          pip install pyinstaller
+          pyinstaller -D crawl_ouchn.spec
+
+      - name: Publish distribution 📦 to Test PyPI
+        uses: pypa/gh-action-pypi-publish@master
+        with:
+          user: __token__
+          password: ${{ secrets.test_pypi_password }}
+          repository_url: https://test.pypi.org/legacy/
+
+      - name: Publish distribution 📦 to PyPI
+        if: startsWith(github.event.ref, 'refs/tags')
+        uses: pypa/gh-action-pypi-publish@master
+        with:
+          user: __token__
+          password: ${{ secrets.pypi_password }}

+ 1 - 1
.gitignore

@@ -1 +1 @@
-/crawl_ouchn/__pycache__/*.pyc
+*.pyc

+ 19 - 0
.vscode/launch.json

@@ -0,0 +1,19 @@
+{
+    "configurations": [
+        {
+            "name": "Docker: Python - General",
+            "type": "docker",
+            "request": "launch",
+            "preLaunchTask": "docker-run: debug",
+            "python": {
+                "pathMappings": [
+                    {
+                        "localRoot": "${workspaceFolder}",
+                        "remoteRoot": "/app"
+                    }
+                ],
+                "projectType": "general"
+            }
+        }
+    ]
+}

+ 26 - 0
.vscode/tasks.json

@@ -0,0 +1,26 @@
+{
+	"version": "2.0.0",
+	"tasks": [
+		{
+			"type": "docker-build",
+			"label": "docker-build",
+			"platform": "python",
+			"dockerBuild": {
+				"tag": "crawlouchn:latest",
+				"dockerfile": "${workspaceFolder}/Dockerfile",
+				"context": "${workspaceFolder}",
+				"pull": true
+			}
+		},
+		{
+			"type": "docker-run",
+			"label": "docker-run: debug",
+			"dependsOn": [
+				"docker-build"
+			],
+			"python": {
+				"file": "main.py"
+			}
+		}
+	]
+}

+ 23 - 0
Dockerfile

@@ -0,0 +1,23 @@
+# For more information, please refer to https://aka.ms/vscode-docker-python
+FROM python:3.8-slim
+
+# Keeps Python from generating .pyc files in the container
+ENV PYTHONDONTWRITEBYTECODE=1
+
+# Turns off buffering for easier container logging
+ENV PYTHONUNBUFFERED=1
+
+# Install pip requirements
+COPY requirements.txt .
+RUN python -m pip install -r requirements.txt
+
+WORKDIR /app
+COPY . /app
+
+# Creates a non-root user with an explicit UID and adds permission to access the /app folder
+# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
+RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
+USER appuser
+
+# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
+CMD ["python", "main.py"]

+ 40 - 1
README.md

@@ -16,8 +16,47 @@
 
 3. downloading some lesson video need to login, So please configure `config/config.json` file `username` and `messageCode`  
 
+## Docker deploy
 
+1. create a `config.json` file, add below in it:
+
+```
+{
+  "username": "15016215661",
+  "messageCode": "123456",
+  "courseUrl": [
+    "http://le.ouchn.cn/#/courseDetails/CAAA010000023530"
+  ]
+}
+```
+
+you want to download a video which need to login. then you neet to modify `usename` and `messageCode`. the `courseUrl` are some urls which you can copy it from browser
+
+2. run the docker container:
+```
+
+docker pull ccr.ccs.tencentyun.com/jianboy/crawl_ouchn:v2022.05.24
+
+docker run -it --rm -v /data/crawl_ouchn/config/config.json:/app/config/config.json -v  /data/crawl_ouchn/Video:/app/Video ccr.ccs.tencentyun.com/jianboy/crawl_ouchn:v2022.05.24
+
+```
 
 ## Development
 
-please read [Develop](./docs/Develop.md)
+please read [Develop](./docs/Develop.md)
+
+### Update History
+
+- [x] Multithreaded download.
+
+- [x] Docker deployment has been implemented.
+
+### Licenses
+
+本项目开源,免费使用,无任何限制,下载的课件视频建议个人使用,请勿以盈利性目的分发哦.
+
+仅供技术交流,有关部门认清形势,请勿随意请喝茶,喝咖啡欢迎!
+
+QQ Group:772583198
+WeChat Group: 
+

+ 6 - 0
bin/crawl_ouchn

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+import crawl_ouchn
+
+if __name__ == '__main__':
+    crawl_ouchn.main()

BIN
config/favicon.ico


+ 17 - 0
crawl_ouchn/__init__.py

@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@Contact :   liuyuqi.gov@msn.cn
+@Time    :   2022/05/24 13:07:28
+@License :   Copyright © 2017-2022 liuyuqi. All Rights Reserved.
+@Desc    :   main function
+'''
+import time
+from crawl_ouchn.crawl_ouchn import CrawlOuchn
+
+
+def main(argv=None):
+    start_time = time.time()
+    crawlOuchn = CrawlOuchn(configPath=r"config/config.json")
+    crawlOuchn.crawl()
+    print("last time: {} s".format(time.time() - start_time))

+ 199 - 0
crawl_ouchn/update.py

@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+'''
+@Contact :   liuyuqi.gov@msn.cn
+@Time    :   2022/05/24 13:13:52
+@License :   Copyright © 2017-2022 liuyuqi. All Rights Reserved.
+@Desc    :   update
+'''
+# todo
+
+from __future__ import unicode_literals
+
+import io
+import json
+import traceback
+import hashlib
+import os
+import subprocess
+import sys
+from zipimport import zipimporter
+
+from .version import __version__
+
+
+def rsa_verify(message, signature, key):
+    from hashlib import sha256
+    assert isinstance(message, bytes)
+    byte_size = (len(bin(key[0])) - 2 + 8 - 1) // 8
+    signature = ('%x' % pow(int(signature, 16), key[1], key[0])).encode()
+    signature = (byte_size * 2 - len(signature)) * b'0' + signature
+    asn1 = b'3031300d060960864801650304020105000420'
+    asn1 += sha256(message).hexdigest().encode()
+    if byte_size < len(asn1) // 2 + 11:
+        return False
+    expected = b'0001' + (byte_size - len(asn1) //
+                          2 - 3) * b'ff' + b'00' + asn1
+    return expected == signature
+
+
+def update_self(to_screen, verbose, opener):
+    """Update the program file with the latest version from the repository"""
+
+    UPDATE_URL = 'https://yt-dl.org/update/'
+    VERSION_URL = UPDATE_URL + 'LATEST_VERSION'
+    JSON_URL = UPDATE_URL + 'versions.json'
+    UPDATES_RSA_KEY = (0x9d60ee4d8f805312fdb15a62f87b95bd66177b91df176765d13514a0f1754bcd2057295c5b6f1d35daa6742c3ffc9a82d3e118861c207995a8031e151d863c9927e304576bc80692bc8e094896fcf11b66f3e29e04e3a71e9a11558558acea1840aec37fc396fb6b65dc81a1c4144e03bd1c011de62e3f1357b327d08426fe93, 65537)
+
+    if not isinstance(globals().get('__loader__'), zipimporter) and not hasattr(sys, 'frozen'):
+        to_screen('It looks like you installed youtube-dl with a package manager, pip, setup.py or a tarball. Please use that to update.')
+        return
+
+    # Check if there is a new version
+    try:
+        newversion = opener.open(VERSION_URL).read().decode('utf-8').strip()
+    except Exception:
+        if verbose:
+            to_screen(encode_compat_str(traceback.format_exc()))
+        to_screen('ERROR: can\'t find the current version. Please try again later.')
+        return
+    if newversion == __version__:
+        to_screen('youtube-dl is up-to-date (' + __version__ + ')')
+        return
+
+    # Download and check versions info
+    try:
+        versions_info = opener.open(JSON_URL).read().decode('utf-8')
+        versions_info = json.loads(versions_info)
+    except Exception:
+        if verbose:
+            to_screen(encode_compat_str(traceback.format_exc()))
+        to_screen('ERROR: can\'t obtain versions info. Please try again later.')
+        return
+    if 'signature' not in versions_info:
+        to_screen('ERROR: the versions file is not signed or corrupted. Aborting.')
+        return
+    signature = versions_info['signature']
+    del versions_info['signature']
+    if not rsa_verify(json.dumps(versions_info, sort_keys=True).encode('utf-8'), signature, UPDATES_RSA_KEY):
+        to_screen('ERROR: the versions file signature is invalid. Aborting.')
+        return
+
+    version_id = versions_info['latest']
+
+    def version_tuple(version_str):
+        return tuple(map(int, version_str.split('.')))
+    if version_tuple(__version__) >= version_tuple(version_id):
+        to_screen('youtube-dl is up to date (%s)' % __version__)
+        return
+
+    to_screen('Updating to version ' + version_id + ' ...')
+    version = versions_info['versions'][version_id]
+
+    print_notes(to_screen, versions_info['versions'])
+
+    # sys.executable is set to the full pathname of the exe-file for py2exe
+    # though symlinks are not followed so that we need to do this manually
+    # with help of realpath
+    filename = compat_realpath(
+        sys.executable if hasattr(sys, 'frozen') else sys.argv[0])
+
+    if not os.access(filename, os.W_OK):
+        to_screen('ERROR: no write permissions on %s' % filename)
+        return
+
+    # Py2EXE
+    if hasattr(sys, 'frozen'):
+        exe = filename
+        directory = os.path.dirname(exe)
+        if not os.access(directory, os.W_OK):
+            to_screen('ERROR: no write permissions on %s' % directory)
+            return
+
+        try:
+            urlh = opener.open(version['exe'][0])
+            newcontent = urlh.read()
+            urlh.close()
+        except (IOError, OSError):
+            if verbose:
+                to_screen(encode_compat_str(traceback.format_exc()))
+            to_screen('ERROR: unable to download latest version')
+            return
+
+        newcontent_hash = hashlib.sha256(newcontent).hexdigest()
+        if newcontent_hash != version['exe'][1]:
+            to_screen('ERROR: the downloaded file hash does not match. Aborting.')
+            return
+
+        try:
+            with open(exe + '.new', 'wb') as outf:
+                outf.write(newcontent)
+        except (IOError, OSError):
+            if verbose:
+                to_screen(encode_compat_str(traceback.format_exc()))
+            to_screen('ERROR: unable to write the new version')
+            return
+
+        try:
+            bat = os.path.join(directory, 'youtube-dl-updater.bat')
+            with io.open(bat, 'w') as batfile:
+                batfile.write('''
+@echo off
+echo Waiting for file handle to be closed ...
+ping 127.0.0.1 -n 5 -w 1000 > NUL
+move /Y "%s.new" "%s" > NUL
+echo Updated youtube-dl to version %s.
+start /b "" cmd /c del "%%~f0"&exit /b"
+                \n''' % (exe, exe, version_id))
+
+            subprocess.Popen([bat])  # Continues to run in the background
+            return  # Do not show premature success messages
+        except (IOError, OSError):
+            if verbose:
+                to_screen(encode_compat_str(traceback.format_exc()))
+            to_screen('ERROR: unable to overwrite current version')
+            return
+
+    # Zip unix package
+    elif isinstance(globals().get('__loader__'), zipimporter):
+        try:
+            urlh = opener.open(version['bin'][0])
+            newcontent = urlh.read()
+            urlh.close()
+        except (IOError, OSError):
+            if verbose:
+                to_screen(encode_compat_str(traceback.format_exc()))
+            to_screen('ERROR: unable to download latest version')
+            return
+
+        newcontent_hash = hashlib.sha256(newcontent).hexdigest()
+        if newcontent_hash != version['bin'][1]:
+            to_screen('ERROR: the downloaded file hash does not match. Aborting.')
+            return
+
+        try:
+            with open(filename, 'wb') as outf:
+                outf.write(newcontent)
+        except (IOError, OSError):
+            if verbose:
+                to_screen(encode_compat_str(traceback.format_exc()))
+            to_screen('ERROR: unable to overwrite current version')
+            return
+
+    to_screen('Updated youtube-dl. Restart youtube-dl to use the new version.')
+
+
+def get_notes(versions, fromVersion):
+    notes = []
+    for v, vdata in sorted(versions.items()):
+        if v > fromVersion:
+            notes.extend(vdata.get('notes', []))
+    return notes
+
+
+def print_notes(to_screen, versions, fromVersion=__version__):
+    notes = get_notes(versions, fromVersion)
+    if notes:
+        to_screen('PLEASE NOTE:')
+        for note in notes:
+            to_screen(note)

+ 3 - 0
crawl_ouchn/version.py

@@ -0,0 +1,3 @@
+from __future__ import unicode_literals
+
+__version__ = '2022.05.24'

+ 11 - 0
docker-compose.debug.yml

@@ -0,0 +1,11 @@
+version: '3.4'
+
+services:
+  crawlouchn:
+    image: crawlouchn
+    build:
+      context: .
+      dockerfile: ./Dockerfile
+    command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 main.py "]
+    ports:
+      - 5678:5678

+ 8 - 0
docker-compose.yml

@@ -0,0 +1,8 @@
+version: '3.4'
+
+services:
+  crawlouchn:
+    image: crawlouchn
+    build:
+      context: .
+      dockerfile: ./Dockerfile

+ 18 - 19
setup.py

@@ -30,20 +30,20 @@ py2exe_options = {
     'dll_excludes': ['w9xpopen.exe', 'crypt32.dll'],
 }
 
-# Get the version from youtube_dl/version.py without importing the package
-exec(compile(open('youtube_dl/version.py').read(),
-             'youtube_dl/version.py', 'exec'))
+# Get the version from crawl_ouchn/version.py without importing the package
+exec(compile(open('crawl_ouchn/version.py').read(),
+             'crawl_ouchn/version.py', 'exec'))
 
-DESCRIPTION = 'YouTube video downloader'
-LONG_DESCRIPTION = 'Command-line program to download videos from YouTube.com and other video sites'
+DESCRIPTION = 'ouchn video downloader'
+LONG_DESCRIPTION = 'downlaod videos from ouchn'
 
 py2exe_console = [{
-    'script': './youtube_dl/__main__.py',
-    'dest_base': 'youtube-dl',
+    'script': './main.py',
+    'dest_base': 'crawl_ouchn',
     'version': __version__,
     'description': DESCRIPTION,
     'comments': LONG_DESCRIPTION,
-    'product_name': 'youtube-dl',
+    'product_name': 'crawl_ouchn',
     'product_version': __version__,
 }]
 
@@ -57,10 +57,10 @@ if len(sys.argv) >= 2 and sys.argv[1] == 'py2exe':
     params = py2exe_params
 else:
     files_spec = [
-        ('etc/bash_completion.d', ['youtube-dl.bash-completion']),
-        ('etc/fish/completions', ['youtube-dl.fish']),
-        ('share/doc/youtube_dl', ['README.txt']),
-        ('share/man/man1', ['youtube-dl.1'])
+        ('etc/bash_completion.d', ['crawl_ouchn.bash-completion']),
+        ('etc/fish/completions', ['crawl_ouchn.fish']),
+        ('share/doc/crawl_ouchn', ['README.txt']),
+        ('share/man/man1', ['crawl_ouchn.1'])
     ]
     root = os.path.dirname(os.path.abspath(__file__))
     data_files = []
@@ -79,9 +79,9 @@ else:
     }
     if setuptools_available:
         params['entry_points'] = {
-            'console_scripts': ['youtube-dl = youtube_dl:main']}
+            'console_scripts': ['crawl_ouchn = crawl_ouchn:main']}
     else:
-        params['scripts'] = ['bin/youtube-dl']
+        params['scripts'] = ['bin/crawl_ouchn']
 
 
 class build_lazy_extractors(Command):
@@ -97,13 +97,13 @@ class build_lazy_extractors(Command):
     def run(self):
         spawn(
             [sys.executable, 'devscripts/make_lazy_extractors.py',
-                'youtube_dl/extractor/lazy_extractors.py'],
+                'crawl_ouchn/extractor/lazy_extractors.py'],
             dry_run=self.dry_run,
         )
 
 
 setup(
-    name='youtube_dl',
+    name='crawl_ouchn',
     version=__version__,
     description=DESCRIPTION,
     long_description=LONG_DESCRIPTION,
@@ -114,9 +114,8 @@ setup(
     maintainer_email='liuyuqi.gov@msn.cn',
     license='Unlicense',
     packages=[
-        'youtube_dl',
-        'youtube_dl.extractor', 'youtube_dl.downloader',
-        'youtube_dl.postprocessor'],
+        'crawl_ouchn',
+        'crawl_ouchn.postprocessor'],
 
     classifiers=[
         'Topic :: Multimedia :: Video',