What I'm working on is something to access MangaDex and check for new chapters, using an albeit old and as far as I can tell decrepit API, however it is the only API I have found for Python. In short, what I believe should be happening is the code uses json.loads() to turn a string gotten from a link, into a dict and then access the keys/values of that dict. However, something is clearly wrong with the string it should be converting.
Traceback starting from relevant code:
newLink = await getLink(mangaName, newChapterNum)
File "/home/eisbar/PycharmProjects/pythonProject1/main.py", line 45, in getLink
link = await mdapi.get_chapter(session, manga, chapter)
File "/home/eisbar/PycharmProjects/pythonProject1/venv/lib/python3.9/site-packages/aiomangadexapi/__init__.py", line 170, in get_chapter
data = await search(session,name)
File "/home/eisbar/PycharmProjects/pythonProject1/venv/lib/python3.9/site-packages/aiomangadexapi/__init__.py", line 129, in search
data = parse(response)
File "/home/eisbar/PycharmProjects/pythonProject1/venv/lib/python3.9/site-packages/aiomangadexapi/__init__.py", line 78, in parse
payload = json.loads(response)
File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
I do understand from the traceback that s to be converted is in some way malformed in the first character. However, here is the string that should be converted, with the links removed:
{"code":200,"status":"OK","data":{"manga":{"id":48959,"title":"Ardor's Kingdom","altTitles":["\uc544\ub354\uc758 \uc655\uad6d"],"description":"An exiled prince's hectic school life in his quest to become the next King Ardor!","artist":["Yoonsoo"],"author":["Yoonsoo"],"publication":{"language":"kr","status":2,"demographic":1},"tags":[5,10,13,36,47],"lastChapter":null,"lastVolume":null,"isHentai":false,"links":{"ap":"ardors-kingdom","mu":"178415","raw":"XXXXXXXX"},"chapters":[{"id":896342,"hash":"db877e42e29ecf94c610d672c5602c19","mangaId":48959,"mangaTitle":"Ardor's Kingdom","volume":"","chapter":"1","title":"","language":"gb","groups":[657],"uploader":1166686,"timestamp":1589822996,"threadId":251978,"comments":4,"views":889}],"groups":[{"id":657,"name":"no group"}]}}
The only explanation I could think of after going through this is that the string above is in some way not passed through the json.loads() chain properly, although I have no clue as to why or how that would happen, or how to test or fix it. As a final note, in case it would help someone if they can touch the source code themselves, the module is aiomangadexapi.py.
Edit0: I'll try my best to add a reprex, but first time doing one that crosses multiple files and into source. Code written by me that requests the link and begins the chain:
async def getLink(manga, chapter):
session = await aiomangadexapi.login('username', 'password')
link = await aiomangadexapi.get_chapter(session, mangaName, chapterNumber) #Point at which traceback errors
await session.close()
return link
Between these is a two-line function that passes mangaName from above to the search function below
async def search(session,name,link=False):
if not link:
name = name.replace(" ", "%20")
name = name.replace("[", "%5B")
name = name.replace("[", "%5D")
name = name.replace("?", "%3F")
response = await fetch(session, 'https://mangadex.org/search?tag_mode_exc=any&tag_mode_inc=all&title={}'.format(name))
link = fetch_link(response)
else:
link = 'https://mangadex.org/' + "api/v2/manga/" + name.split("title/")[1].split('/',1)[0] + "?include=chapters"
response = await fetch(session, link) #this line previously in source was not indented, however it caused a separate error that was fixed when indented.
data = parse(response) #Point at which Traceback errors
return data
The final code before it enters built-in python JSON files, going through loads - decode - raw_decode in the traceback.
def parse(response):
GENRES = {
#Removed here because not necessary and/or certain parts against SO rules
}
payload = json.loads(response) #Point at which traceback errors.
data, chapters = payload['data']['manga'], payload['data']['chapters']
#More code relating to the data variable below this, however removed as it is not executed due to code erroring on payload definition.
return [data]