Handling JSONDecodeError
This commit is contained in:
@@ -1,46 +1,52 @@
|
|||||||
class ChatParseException(Exception):
|
class ChatParseException(Exception):
|
||||||
'''
|
'''
|
||||||
チャットデータをパースするライブラリが投げる例外の基底クラス
|
Base exception thrown by the parser
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class NoYtinitialdataException(ChatParseException):
|
class NoYtinitialdataException(ChatParseException):
|
||||||
'''
|
'''
|
||||||
配信ページ内にチャットデータurlが見つからないときに投げる例外
|
Thrown when the video is not found.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class ResponseContextError(ChatParseException):
|
class ResponseContextError(ChatParseException):
|
||||||
'''
|
'''
|
||||||
配信ページでチャットデータ無効の時に投げる例外
|
Thrown when chat data is invalid.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class NoLivechatRendererException(ChatParseException):
|
class NoLivechatRendererException(ChatParseException):
|
||||||
'''
|
'''
|
||||||
チャットデータのJSON中にlivechatRendererがない時に投げる例外
|
Thrown when livechatRenderer is missing in JSON.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoContentsException(ChatParseException):
|
class NoContentsException(ChatParseException):
|
||||||
'''
|
'''
|
||||||
チャットデータのJSON中にContinuationContentsがない時に投げる例外
|
Thrown when ContinuationContents is missing in JSON.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class NoContinuationsException(ChatParseException):
|
class NoContinuationsException(ChatParseException):
|
||||||
'''
|
'''
|
||||||
チャットデータのContinuationContents中にcontinuationがない時に投げる例外
|
Thrown when continuation is missing in ContinuationContents.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class IllegalFunctionCall(Exception):
|
class IllegalFunctionCall(Exception):
|
||||||
'''
|
'''
|
||||||
set_callback()を実行済みにもかかわらず
|
Thrown when get () is called even though
|
||||||
get()を呼び出した場合の例外
|
set_callback () has been executed.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class InvalidVideoIdException(Exception):
|
class InvalidVideoIdException(Exception):
|
||||||
|
'''
|
||||||
|
Thrown when the video_id is not exist (VideoInfo).
|
||||||
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class UnknownConnectionError(Exception):
|
||||||
|
pass
|
||||||
@@ -7,12 +7,15 @@ from . worker import ExtractWorker
|
|||||||
from . patch import Patch
|
from . patch import Patch
|
||||||
from ... import config
|
from ... import config
|
||||||
from ... paramgen import arcparam
|
from ... paramgen import arcparam
|
||||||
|
from ... exceptions import UnknownConnectionError
|
||||||
from concurrent.futures import CancelledError
|
from concurrent.futures import CancelledError
|
||||||
|
from json import JSONDecodeError
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
headers = config.headers
|
headers = config.headers
|
||||||
REPLAY_URL = "https://www.youtube.com/live_chat_replay/" \
|
REPLAY_URL = "https://www.youtube.com/live_chat_replay/" \
|
||||||
"get_live_chat_replay?continuation="
|
"get_live_chat_replay?continuation="
|
||||||
|
MAX_RETRY_COUNT = 3
|
||||||
|
|
||||||
def _split(start, end, count, min_interval_sec = 120):
|
def _split(start, end, count, min_interval_sec = 120):
|
||||||
"""
|
"""
|
||||||
@@ -53,13 +56,22 @@ def ready_blocks(video_id, duration, div, callback):
|
|||||||
tasks = [_create_block(session, video_id, seektime, callback)
|
tasks = [_create_block(session, video_id, seektime, callback)
|
||||||
for seektime in _split(-1, duration, div)]
|
for seektime in _split(-1, duration, div)]
|
||||||
return await asyncio.gather(*tasks)
|
return await asyncio.gather(*tasks)
|
||||||
|
|
||||||
async def _create_block(session, video_id, seektime, callback):
|
async def _create_block(session, video_id, seektime, callback):
|
||||||
continuation = arcparam.getparam(video_id, seektime = seektime)
|
continuation = arcparam.getparam(video_id, seektime = seektime)
|
||||||
url = f"{REPLAY_URL}{quote(continuation)}&pbj=1"
|
url = f"{REPLAY_URL}{quote(continuation)}&pbj=1"
|
||||||
async with session.get(url, headers = headers) as resp:
|
for _ in range(MAX_RETRY_COUNT):
|
||||||
text = await resp.text()
|
try :
|
||||||
next_continuation, actions = parser.parse(json.loads(text))
|
async with session.get(url, headers = headers) as resp:
|
||||||
|
text = await resp.text()
|
||||||
|
next_continuation, actions = parser.parse(json.loads(text))
|
||||||
|
break
|
||||||
|
except JSONDecodeError:
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
else:
|
||||||
|
cancel()
|
||||||
|
raise UnknownConnectionError("Abort: Unknown connection error.")
|
||||||
|
|
||||||
if actions:
|
if actions:
|
||||||
first = parser.get_offset(actions[0])
|
first = parser.get_offset(actions[0])
|
||||||
last = parser.get_offset(actions[-1])
|
last = parser.get_offset(actions[-1])
|
||||||
@@ -71,6 +83,7 @@ def ready_blocks(video_id, duration, div, callback):
|
|||||||
first = first,
|
first = first,
|
||||||
last = last
|
last = last
|
||||||
)
|
)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
fetch initial blocks.
|
fetch initial blocks.
|
||||||
"""
|
"""
|
||||||
@@ -95,9 +108,18 @@ def fetch_patch(callback, blocks, video_id):
|
|||||||
|
|
||||||
async def _fetch(continuation,session) -> Patch:
|
async def _fetch(continuation,session) -> Patch:
|
||||||
url = f"{REPLAY_URL}{quote(continuation)}&pbj=1"
|
url = f"{REPLAY_URL}{quote(continuation)}&pbj=1"
|
||||||
async with session.get(url,headers = config.headers) as resp:
|
for _ in range(MAX_RETRY_COUNT):
|
||||||
chat_json = await resp.text()
|
try:
|
||||||
continuation, actions = parser.parse(json.loads(chat_json))
|
async with session.get(url,headers = config.headers) as resp:
|
||||||
|
chat_json = await resp.text()
|
||||||
|
continuation, actions = parser.parse(json.loads(chat_json))
|
||||||
|
break
|
||||||
|
except JSONDecodeError:
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
else:
|
||||||
|
cancel()
|
||||||
|
raise UnknownConnectionError("Abort: Unknown connection error.")
|
||||||
|
|
||||||
if actions:
|
if actions:
|
||||||
last = parser.get_offset(actions[-1])
|
last = parser.get_offset(actions[-1])
|
||||||
first = parser.get_offset(actions[0])
|
first = parser.get_offset(actions[0])
|
||||||
@@ -105,6 +127,7 @@ def fetch_patch(callback, blocks, video_id):
|
|||||||
callback(actions, last - first)
|
callback(actions, last - first)
|
||||||
return Patch(actions, continuation, first, last)
|
return Patch(actions, continuation, first, last)
|
||||||
return Patch(continuation = continuation)
|
return Patch(continuation = continuation)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
allocate workers and assign blocks.
|
allocate workers and assign blocks.
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user