parsehub 2.3.4__tar.gz → 2.3.5__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.4/src/parsehub.egg-info → parsehub-2.3.5}/PKG-INFO +1 -1
- {parsehub-2.3.4 → parsehub-2.3.5}/pyproject.toml +1 -1
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/bilibili.py +2 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/kuaishou.py +12 -2
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/kuaishou.py +10 -2
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/twitter.py +7 -0
- {parsehub-2.3.4 → parsehub-2.3.5/src/parsehub.egg-info}/PKG-INFO +1 -1
- {parsehub-2.3.4 → parsehub-2.3.5}/LICENSE +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/README.md +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/setup.cfg +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/cli.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/cli_config.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/config/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/config/config.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/errors.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/base/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/base/base.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/base/ytdlp.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/bangumi.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/coolapk.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/douban.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/douyin.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/facebook.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/instagram.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/medium.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/pipix.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/snapchat.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/threads.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/tieba.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/tiktok.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/toutiao.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/twitter.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/weibo.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/weixin.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/wxchannels.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/xhs.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/xiaoheihe.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/youtube.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/zhihu.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/parsers/parser/zuiyou.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/bangumi.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/bilibili.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/coolapk.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/douban.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/douyin.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/instagram.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/medium.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/pipix.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/threads.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/tieba.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/tiktok.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/toutiao.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/weibo.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/weixin.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/wxchannels.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/xhs.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/xiaoheihe.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/zhihu.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/provider_api/zuiyou.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/__init__.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/callback.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/media_file.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/media_ref.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/platform.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/post.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/types/result.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/utils/downloader.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/utils/helpers.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub/utils/media_info.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub.egg-info/SOURCES.txt +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub.egg-info/dependency_links.txt +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub.egg-info/entry_points.txt +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub.egg-info/requires.txt +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/src/parsehub.egg-info/top_level.txt +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/test/test_cli.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/test/test_cli_config.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/test/test_core_offline.py +0 -0
- {parsehub-2.3.4 → parsehub-2.3.5}/test/test_downloader.py +0 -0
|
@@ -31,6 +31,8 @@ class BiliParse(BaseParser):
|
|
|
31
31
|
__redirect_keywords__ = ["b23.tv", "bili2233.cn"]
|
|
32
32
|
|
|
33
33
|
async def _do_parse(self, raw_url: str) -> YtVideoParseResult | BiliVideoParseResult | ImageParseResult:
|
|
34
|
+
if urlparse(raw_url).path.startswith("/bangumi/"):
|
|
35
|
+
raise ParseError("不支持解析番剧和影视")
|
|
34
36
|
if await self.is_dynamic(raw_url):
|
|
35
37
|
dynamic = await self.get_dynamic_info(raw_url)
|
|
36
38
|
content = self.hashtag_handler(dynamic.content or "")
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
from ...provider_api.kuaishou import KuaiShouAPI, KuaishouParser
|
|
2
|
-
from ...types import
|
|
2
|
+
from ...types import (
|
|
3
|
+
ContentUnavailableError,
|
|
4
|
+
ImageParseResult,
|
|
5
|
+
ImageRef,
|
|
6
|
+
ParseError,
|
|
7
|
+
Platform,
|
|
8
|
+
VideoParseResult,
|
|
9
|
+
VideoRef,
|
|
10
|
+
)
|
|
3
11
|
from ...utils.helpers import SecretCookie
|
|
4
12
|
from ..base.base import BaseParser, FallbackStage
|
|
5
13
|
|
|
@@ -26,13 +34,15 @@ COOKIE = SecretCookie(
|
|
|
26
34
|
class KuaiShouParser(BaseParser):
|
|
27
35
|
__platform__ = Platform.KUAISHOU
|
|
28
36
|
__supported_type__ = ["视频", "图文"]
|
|
29
|
-
__match__ = r"^(http(s)?://)?(www|v|live|v\.m)\.(kuaishou|chenzhongtech).com/.+"
|
|
37
|
+
__match__ = r"^(http(s)?://)?(www|v|live|v\.m|[a-z0-9]+\.m)\.(kuaishou|chenzhongtech).com/.+"
|
|
30
38
|
__redirect_keywords__ = ["v.kuaishou", "/f/"]
|
|
31
39
|
|
|
32
40
|
async def _do_parse(self, raw_url: str) -> VideoParseResult | ImageParseResult:
|
|
33
41
|
ksp = await KuaishouParser.create(
|
|
34
42
|
raw_url, proxy=self.proxy, cookie=self.cookie.get_value() or COOKIE.get_value()
|
|
35
43
|
)
|
|
44
|
+
if ksp.page_type == "UNKNOWN" and ksp.error_result in (223, 20113):
|
|
45
|
+
raise ContentUnavailableError(f"{ksp.error_result} {ksp.error_msg}")
|
|
36
46
|
if (
|
|
37
47
|
ksp.page_type == "VIDEO" or "/short-video/" in raw_url
|
|
38
48
|
): # 地区风控导致获取到的 page_type 可能为 ATLAS 但实际为视频
|
|
@@ -212,6 +212,8 @@ class KuaishouParser:
|
|
|
212
212
|
self.page_type = "UNKNOWN"
|
|
213
213
|
self.structured_data: dict = {}
|
|
214
214
|
self.client: dict = {}
|
|
215
|
+
self.error_result: int | None = None
|
|
216
|
+
self.error_msg: str | None = None
|
|
215
217
|
|
|
216
218
|
@classmethod
|
|
217
219
|
async def create(cls, real_url, proxy: str | None = None, cookie: dict | None = None):
|
|
@@ -319,8 +321,10 @@ class KuaishouParser:
|
|
|
319
321
|
return False
|
|
320
322
|
if default_client.get("VisionVideoSetRepresentation:1"):
|
|
321
323
|
return True
|
|
322
|
-
for key in default_client.
|
|
323
|
-
if "visionVideoDetail" in key
|
|
324
|
+
for key, value in default_client.items():
|
|
325
|
+
if "visionVideoDetail" in key and isinstance(value, dict) and value.get("photo"):
|
|
326
|
+
return True
|
|
327
|
+
if "VisionVideoDetailPhoto:" in key:
|
|
324
328
|
return True
|
|
325
329
|
return False
|
|
326
330
|
|
|
@@ -333,6 +337,10 @@ class KuaishouParser:
|
|
|
333
337
|
page_type, structured_data = self._identify_and_parse_data()
|
|
334
338
|
if page_type == "UNKNOWN" or not structured_data:
|
|
335
339
|
return False
|
|
340
|
+
error_payload = self._find_nested_dict(structured_data, ("result", "error_msg"))
|
|
341
|
+
if error_payload and error_payload["result"] != 1 and error_payload["error_msg"]:
|
|
342
|
+
self.error_result = error_payload["result"]
|
|
343
|
+
self.error_msg = error_payload["error_msg"]
|
|
336
344
|
if not self._is_valid_video_state(page_type, structured_data):
|
|
337
345
|
logger.warning(f"Kuaishou route {candidate_url} returned incomplete video state, trying fallback")
|
|
338
346
|
return False
|
|
@@ -91,6 +91,13 @@ class Twitter:
|
|
|
91
91
|
if not legacy:
|
|
92
92
|
if result.get("__typename") == "TweetTombstone":
|
|
93
93
|
raise Exception("error -2: 该推文开启了限制, 匿名用户无法查看")
|
|
94
|
+
match result.get("reason"):
|
|
95
|
+
case "Suspended":
|
|
96
|
+
raise ContentUnavailableError("error -5: 这个帖子来自一个被冻结的账号")
|
|
97
|
+
case "BounceDeleted":
|
|
98
|
+
raise ContentUnavailableError("error -5: 这个帖子违反了 X 规则")
|
|
99
|
+
case "Protected":
|
|
100
|
+
raise Exception("error -3: 你无法查看这个帖子,因为该账号所有者限制了可以查看其帖子的用户")
|
|
94
101
|
raise Exception(f"error -3: {result.get('reason')}")
|
|
95
102
|
|
|
96
103
|
if article := result.get("article", {}):
|
|
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
|