Handling JSONDecodeError

This commit is contained in:
taizan-hokuto
2020-03-14 08:00:31 +09:00
parent 5f50598f79
commit 21d93613a2
2 changed files with 44 additions and 15 deletions

View File

@@ -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

View File

@@ -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.
""" """