mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-26 17:21:23 +01:00
Compare commits
10 Commits
a5ac21900a
...
44215b47ee
Author | SHA1 | Date | |
---|---|---|---|
|
44215b47ee | ||
|
b83ca24eb7 | ||
|
240a7d43c8 | ||
|
f13df591d4 | ||
|
75432034fe | ||
|
48e821ab16 | ||
|
b7f94ef67a | ||
|
0d917bba3f | ||
|
314fce0c43 | ||
|
98a3cb0823 |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
|
@ -504,7 +504,8 @@ jobs:
|
||||||
- windows32
|
- windows32
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v4
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: artifact
|
path: artifact
|
||||||
pattern: build-bin-*
|
pattern: build-bin-*
|
||||||
|
|
17
.github/workflows/release-master.yml
vendored
17
.github/workflows/release-master.yml
vendored
|
@ -28,3 +28,20 @@ jobs:
|
||||||
actions: write # For cleaning up cache
|
actions: write # For cleaning up cache
|
||||||
id-token: write # mandatory for trusted publishing
|
id-token: write # mandatory for trusted publishing
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
publish_pypi:
|
||||||
|
needs: [release]
|
||||||
|
if: vars.MASTER_PYPI_PROJECT != ''
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
id-token: write # mandatory for trusted publishing
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: dist
|
||||||
|
name: build-pypi
|
||||||
|
- name: Publish to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
verbose: true
|
||||||
|
|
17
.github/workflows/release-nightly.yml
vendored
17
.github/workflows/release-nightly.yml
vendored
|
@ -41,3 +41,20 @@ jobs:
|
||||||
actions: write # For cleaning up cache
|
actions: write # For cleaning up cache
|
||||||
id-token: write # mandatory for trusted publishing
|
id-token: write # mandatory for trusted publishing
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
publish_pypi:
|
||||||
|
needs: [release]
|
||||||
|
if: vars.NIGHTLY_PYPI_PROJECT != ''
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
id-token: write # mandatory for trusted publishing
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: dist
|
||||||
|
name: build-pypi
|
||||||
|
- name: Publish to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
verbose: true
|
||||||
|
|
19
.github/workflows/release.yml
vendored
19
.github/workflows/release.yml
vendored
|
@ -2,10 +2,6 @@ name: Release
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
prerelease:
|
|
||||||
required: false
|
|
||||||
default: true
|
|
||||||
type: boolean
|
|
||||||
source:
|
source:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
@ -18,6 +14,10 @@ on:
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
type: string
|
type: string
|
||||||
|
prerelease:
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
source:
|
source:
|
||||||
|
@ -278,11 +278,20 @@ jobs:
|
||||||
make clean-cache
|
make clean-cache
|
||||||
python -m build --no-isolation .
|
python -m build --no-isolation .
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
if: github.event_name != 'workflow_dispatch'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-pypi
|
||||||
|
path: |
|
||||||
|
dist/*
|
||||||
|
compression-level: 0
|
||||||
|
|
||||||
- name: Publish to PyPI
|
- name: Publish to PyPI
|
||||||
|
if: github.event_name == 'workflow_dispatch'
|
||||||
uses: pypa/gh-action-pypi-publish@release/v1
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
with:
|
with:
|
||||||
verbose: true
|
verbose: true
|
||||||
attestations: false # Currently doesn't work w/ reusable workflows (breaks nightly)
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
needs: [prepare, build]
|
needs: [prepare, build]
|
||||||
|
|
|
@ -52,7 +52,7 @@ default = [
|
||||||
"pycryptodomex",
|
"pycryptodomex",
|
||||||
"requests>=2.32.2,<3",
|
"requests>=2.32.2,<3",
|
||||||
"urllib3>=1.26.17,<3",
|
"urllib3>=1.26.17,<3",
|
||||||
"websockets>=13.0",
|
"websockets>=13.0,<14",
|
||||||
]
|
]
|
||||||
curl-cffi = [
|
curl-cffi = [
|
||||||
"curl-cffi==0.5.10; os_name=='nt' and implementation_name=='cpython'",
|
"curl-cffi==0.5.10; os_name=='nt' and implementation_name=='cpython'",
|
||||||
|
|
|
@ -24,7 +24,7 @@ try:
|
||||||
from Crypto.Cipher import AES, PKCS1_OAEP, Blowfish, PKCS1_v1_5 # noqa: F401
|
from Crypto.Cipher import AES, PKCS1_OAEP, Blowfish, PKCS1_v1_5 # noqa: F401
|
||||||
from Crypto.Hash import CMAC, SHA1 # noqa: F401
|
from Crypto.Hash import CMAC, SHA1 # noqa: F401
|
||||||
from Crypto.PublicKey import RSA # noqa: F401
|
from Crypto.PublicKey import RSA # noqa: F401
|
||||||
except ImportError:
|
except (ImportError, OSError):
|
||||||
__version__ = f'broken {__version__}'.strip()
|
__version__ = f'broken {__version__}'.strip()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -918,6 +918,9 @@ from .japandiet import (
|
||||||
ShugiinItvLiveRoomIE,
|
ShugiinItvLiveRoomIE,
|
||||||
ShugiinItvVodIE,
|
ShugiinItvVodIE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .jditemvideo import JdItemVideoIE
|
||||||
|
|
||||||
from .jeuxvideo import JeuxVideoIE
|
from .jeuxvideo import JeuxVideoIE
|
||||||
from .jiocinema import (
|
from .jiocinema import (
|
||||||
JioCinemaIE,
|
JioCinemaIE,
|
||||||
|
|
86
yt_dlp/extractor/jditemvideo.py
Normal file
86
yt_dlp/extractor/jditemvideo.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import determine_ext, ExtractorError, traverse_obj
|
||||||
|
|
||||||
|
|
||||||
|
class JdItemVideoIE(InfoExtractor):
|
||||||
|
_VALID_URL = r"https://.+.jd.[a-z\.]{2,9}/(?P<id>\d{6,16}).html"
|
||||||
|
|
||||||
|
IE_NAME = 'jd-video'
|
||||||
|
IE_DESC = 'jd-video extractor'
|
||||||
|
_NETRC_MACHINE = False
|
||||||
|
|
||||||
|
_JD_API_VIDEO_CALLBACK_URL = 'https://cd.jd.com/tencent/video_v3?callback=jQuery{rand}&vid={video_id}&type=1&from=1&appid=24&_={timestamp}'
|
||||||
|
|
||||||
|
_TESTS = [
|
||||||
|
{
|
||||||
|
'url': 'https://npcitem.jd.hk/100030101538.html',
|
||||||
|
'info_dict': {
|
||||||
|
"id": "100030101538",
|
||||||
|
"ext": "mp4",
|
||||||
|
"title": "ipad 2021第九代",
|
||||||
|
"description": "【AppleiPad】Apple苹果 iPad 第9代 10.2英寸平板电脑 2021款 ipad9(64GB WLAN版/A13芯片/1200万像素/iPadOS)深空灰色【行情 报价 价格 评测】-京东",
|
||||||
|
"size": 10251794,
|
||||||
|
"width": 1280,
|
||||||
|
"height": 1280,
|
||||||
|
"duration": 56,
|
||||||
|
"thumbnail": "https://jvod.300hu.com/img/2022/130871763/1/img7.jpg",
|
||||||
|
"url": "https://jvod.300hu.com/vod/product/6e02e2d8-98bc-491d-80a1-448ae5ea1c38/c6ef7b9b14ef4b9ca7e4cebda5b7684c.mp4?source=2&h265=h265/18799/a797504bd6f947dfbf6fdb96acfbb55f.mp4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': 'https://npcitem.jd.hk/100030101538.html',
|
||||||
|
'info_dict': {
|
||||||
|
"id": "100037516759",
|
||||||
|
"ext": "mp4",
|
||||||
|
"title": "RODE Wireless Go II Dual",
|
||||||
|
"description": "【RODEWireless Go II Dual】罗德(RODE)Wireless Go II Dual无线领夹麦克风单反手机无线小蜜蜂采访直播vlog收音 一拖二2代 标配【行情 报价 价格 评测】-京东",
|
||||||
|
"size": 7547769,
|
||||||
|
"width": 1280,
|
||||||
|
"height": 720,
|
||||||
|
"duration": 60,
|
||||||
|
"thumbnail": "https://jvod.300hu.com/img/2022/219535842/1/img7.jpg",
|
||||||
|
"url": "https://jvod.300hu.com/vod/product/1fc0661d-546e-446e-a429-a8db696ab06a/4067f4c3bb2d41c5af84081d2b0e3018.mp4?source=2&h265=h265/113074/cf365c28ca3a4fdb8178c4e44f916341.mp4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
item_id = self._match_id(url=url)
|
||||||
|
resp = self._download_webpage(url_or_request=url, video_id=item_id)
|
||||||
|
pattern_data = self._html_search_regex(pattern=r'"mainVideoId":"(\d+?)"', string=resp, name='videoId')
|
||||||
|
if pattern_data is None:
|
||||||
|
raise ExtractorError("There are no any video. %s" % url)
|
||||||
|
|
||||||
|
description = self._html_extract_title(resp)
|
||||||
|
rand = random.randint(433333, 999999)
|
||||||
|
timestamp = int(time.time() * 1000)
|
||||||
|
url = self._JD_API_VIDEO_CALLBACK_URL.format(rand=rand, timestamp=timestamp, video_id=pattern_data)
|
||||||
|
mp4resp = self._download_webpage(url_or_request=url, video_id=item_id)
|
||||||
|
detailResp = self._html_search_regex(pattern=r'jQuery\d+\((.+)\)', string=mp4resp, name='detail')
|
||||||
|
if detailResp is None:
|
||||||
|
raise ExtractorError("Callback fail. return: %s" % detailResp)
|
||||||
|
|
||||||
|
detailRespJson = json.loads(detailResp)
|
||||||
|
if detailRespJson.get("code", -1) != 0:
|
||||||
|
raise ExtractorError("Callback fail. return: %s" % detailResp)
|
||||||
|
|
||||||
|
ext = determine_ext(url=detailRespJson.get("playUrl", ""))
|
||||||
|
|
||||||
|
info_dict = {
|
||||||
|
'id': item_id,
|
||||||
|
'ext': ext,
|
||||||
|
'title': traverse_obj(detailRespJson, ('extInfo', 'videoName'), default="unknown_video_title"),
|
||||||
|
'description': description,
|
||||||
|
'size': traverse_obj(detailRespJson, ("extInfo", "size")),
|
||||||
|
'width': traverse_obj(detailRespJson, ("extInfo", "vwidth")),
|
||||||
|
'height': traverse_obj(detailRespJson, ("extInfo", "vheight")),
|
||||||
|
'duration': detailRespJson.get("duration"),
|
||||||
|
'thumbnail': detailRespJson.get("imageUrl"),
|
||||||
|
'url': detailRespJson.get("playUrl")
|
||||||
|
}
|
||||||
|
return info_dict
|
Loading…
Reference in New Issue
Block a user