parsehub 2.3.13__tar.gz → 2.3.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {parsehub-2.3.13/src/parsehub.egg-info → parsehub-2.3.14}/PKG-INFO +1 -1
- {parsehub-2.3.13 → parsehub-2.3.14}/pyproject.toml +1 -1
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/bilibili.py +8 -9
- {parsehub-2.3.13 → parsehub-2.3.14/src/parsehub.egg-info}/PKG-INFO +1 -1
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub.egg-info/SOURCES.txt +1 -0
- parsehub-2.3.14/test/test_bilibili_offline.py +63 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/LICENSE +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/README.md +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/setup.cfg +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/cli.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/cli_config.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/config/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/config/config.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/errors.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/base/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/base/base.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/base/ytdlp.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/bangumi.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/coolapk.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/douban.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/douyin.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/facebook.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/instagram.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/kuaishou.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/medium.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/pipix.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/snapchat.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/threads.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/tieba.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/tiktok.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/toutiao.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/twitter.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/weibo.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/weixin.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/wxchannels.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/xhs.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/xiaoheihe.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/youtube.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/zhihu.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/parsers/parser/zuiyou.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/bangumi.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/bilibili.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/coolapk.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/douban.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/douyin.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/instagram.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/kuaishou.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/medium.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/pipix.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/threads.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/tieba.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/tiktok.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/toutiao.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/twitter.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/weibo.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/weixin.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/wxchannels.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/xhs.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/xiaoheihe.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/zhihu.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/provider_api/zuiyou.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/__init__.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/callback.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/media_file.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/media_ref.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/platform.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/post.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/types/result.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/utils/downloader.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/utils/fallback.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/utils/helpers.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub/utils/media_info.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub.egg-info/dependency_links.txt +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub.egg-info/entry_points.txt +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub.egg-info/requires.txt +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/src/parsehub.egg-info/top_level.txt +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/test/test_cli.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/test/test_cli_config.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/test/test_core_offline.py +0 -0
- {parsehub-2.3.13 → parsehub-2.3.14}/test/test_downloader.py +0 -0
|
@@ -112,17 +112,16 @@ class BiliParse(BaseParser):
|
|
|
112
112
|
p = int(parse_qs(urlparse(url).query).get("p", ["1"])[0])
|
|
113
113
|
view = data["View"]
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
pages = view.get("pages") or []
|
|
116
|
+
page_info = next((i for i in pages if i["page"] == p), None)
|
|
117
|
+
if page_info is None and pages:
|
|
118
|
+
page_info = pages[0] # p 越界时回退默认P
|
|
119
|
+
|
|
120
|
+
cid = page_info["cid"] if page_info else view["cid"]
|
|
121
|
+
duration = page_info["duration"] if page_info else view["duration"]
|
|
122
|
+
dimension = page_info["dimension"] if page_info else view["dimension"]
|
|
118
123
|
desc = view["desc"]
|
|
119
124
|
|
|
120
|
-
if p != 1 and (pages := view.get("pages")):
|
|
121
|
-
if page_info := next((i for i in pages if i["page"] == p), None):
|
|
122
|
-
cid = page_info["cid"]
|
|
123
|
-
duration = page_info["duration"]
|
|
124
|
-
dimension = page_info["dimension"]
|
|
125
|
-
|
|
126
125
|
b3, b4 = await bili.get_buvid()
|
|
127
126
|
video_playurl = await bili.get_video_playurl(url, cid, b3, b4)
|
|
128
127
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
|
|
4
|
+
from parsehub.parsers.parser.bilibili import BiliParse
|
|
5
|
+
|
|
6
|
+
VIEW = {
|
|
7
|
+
"cid": 111,
|
|
8
|
+
"duration": 769,
|
|
9
|
+
"dimension": {"width": 1920, "height": 1080},
|
|
10
|
+
"desc": "",
|
|
11
|
+
"title": "test",
|
|
12
|
+
"pic": "https://cdn.example/cover.jpg",
|
|
13
|
+
"pages": [
|
|
14
|
+
{"page": 1, "cid": 111, "duration": 190, "dimension": {"width": 1920, "height": 1080}},
|
|
15
|
+
{"page": 2, "cid": 222, "duration": 193, "dimension": {"width": 1920, "height": 1080}},
|
|
16
|
+
],
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FakeBiliAPI:
|
|
21
|
+
last_cid = None
|
|
22
|
+
|
|
23
|
+
def __init__(self, proxy=None):
|
|
24
|
+
self.proxy = proxy
|
|
25
|
+
|
|
26
|
+
async def __aenter__(self):
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
async def __aexit__(self, *args):
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
async def get_video_info(self, url):
|
|
33
|
+
return {"data": {"View": VIEW}}
|
|
34
|
+
|
|
35
|
+
async def get_buvid(self):
|
|
36
|
+
return "b3", "b4"
|
|
37
|
+
|
|
38
|
+
async def get_video_playurl(self, url, cid, b3, b4):
|
|
39
|
+
FakeBiliAPI.last_cid = cid
|
|
40
|
+
return {"data": {"durl": [{"url": "https://cdn.example/video.mp4"}]}}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TestBilibiliParts(unittest.IsolatedAsyncioTestCase):
|
|
44
|
+
async def test_default_part_uses_first_page_duration(self):
|
|
45
|
+
with patch("parsehub.parsers.parser.bilibili.BiliAPI", FakeBiliAPI):
|
|
46
|
+
result = await BiliParse().bili_api_parse("https://www.bilibili.com/video/BV1zLap6VEz1/")
|
|
47
|
+
|
|
48
|
+
self.assertEqual(result.media.duration, 190)
|
|
49
|
+
self.assertEqual(FakeBiliAPI.last_cid, 111)
|
|
50
|
+
|
|
51
|
+
async def test_requested_part_uses_page_duration(self):
|
|
52
|
+
with patch("parsehub.parsers.parser.bilibili.BiliAPI", FakeBiliAPI):
|
|
53
|
+
result = await BiliParse().bili_api_parse("https://www.bilibili.com/video/BV1zLap6VEz1/?p=2")
|
|
54
|
+
|
|
55
|
+
self.assertEqual(result.media.duration, 193)
|
|
56
|
+
self.assertEqual(FakeBiliAPI.last_cid, 222)
|
|
57
|
+
|
|
58
|
+
async def test_out_of_range_falls_back_to_default_part(self):
|
|
59
|
+
with patch("parsehub.parsers.parser.bilibili.BiliAPI", FakeBiliAPI):
|
|
60
|
+
result = await BiliParse().bili_api_parse("https://www.bilibili.com/video/BV1zLap6VEz1/?p=99")
|
|
61
|
+
|
|
62
|
+
self.assertEqual(result.media.duration, 190)
|
|
63
|
+
self.assertEqual(FakeBiliAPI.last_cid, 111)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|