aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md53
-rw-r--r--requirements.txt2
-rw-r--r--walker.py106
3 files changed, 161 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9e1a6c3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
+# comicwalker-dl
+
+A python tool to download free manga/comic from [ComicWalker](https://comic-walker.com/ "ComicWalker official website").
+
+The downloaded images are untouched and original from source, they are not modified in any way. flow:
+
+> image source (.webp) -> download process by python script -> output (.webp)
+
+## Requirements
+- python version 3
+- essential modules on `requirements.txt`, do `pip install -r requirements.txt`
+ - for all modules see inside the code
+
+## Usage
+this tool is a standalone python script, you can download the files as a zip/git clone, or just download `walker.py` and the requirements is enough.
+
+0. prep the requirements beforehand
+1. put `walker.py` in a folder of your choice
+2. open a terminal (.i.e CMD) in that folder
+3. see below for detailed usage
+
+all downloaded chapters are saved to `/downloaded_chapters/{title}/{chapter}`
+
+---
+```
+usage: walker.py [-h] [-cid CID] [-nolog]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -cid CID content id, &cid={...}. see url when reading a chapter
+ -nolog no progressive download logs on terminal
+```
+---
+
+to download a chapter, simply run the .py script by:
+
+```> python walker.py -cid [CID]```
+
+---
+
+example:
+
+```> python walker.py -cid KDCW_CW01000002010001_68```
+
+---
+
+add `-nolog` argument if you want clean terminal output during the progress.
+
+```> python walker.py -cid KDCW_CW01000002010001_68 -nolog```
+
+---
+
+feel free to modify the code as you wish. \ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..9fe49be
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+coloredlogs
+requests
diff --git a/walker.py b/walker.py
new file mode 100644
index 0000000..6febfb2
--- /dev/null
+++ b/walker.py
@@ -0,0 +1,106 @@
+import argparse
+import coloredlogs
+import json
+import logging
+import os
+import requests
+import sys
+
+from binascii import unhexlify
+
+os.system('cls||clear')
+
+print('COMICWALKER-DL\n')
+
+coloredlogs.install(fmt='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s')
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-cid', help='content id, &cid={...}. see url when reading a chapter')
+parser.add_argument('-nolog', help='no progressive download logs on terminal', action="store_true")
+args = parser.parse_args(args=None if sys.argv[1:] else ['--help'])
+
+if args.cid == None:
+ parser.print_help()
+ sys.exit()
+
+def start(url, headers):
+ meta = json.loads(requests.get(url=url, headers=headers).content)
+ img_url = f'{url}/frames?enable_webp=true'
+
+ try:
+ cid_info = {
+ "TITLE": meta['data']['extra']['content']['title'],
+ "CHAPTER": meta['data']['result']['title']
+ }
+
+ except KeyError:
+ logging.error("Metadata malformed, check CID's validity")
+ sys.exit()
+
+ else:
+ print('{} - {}'.format(cid_info['TITLE'], cid_info['CHAPTER']))
+
+ undrm(img_url, headers, cid_info)
+
+def undrm(url, headers, cid_info):
+ meta = json.loads(requests.get(url=url, headers=headers).content)
+
+ print('Page count: {}\n'.format(len(meta['data']['result'])))
+
+ save_path = os.path.join('downloaded_chapters\\{}\\{}'.format(cid_info['TITLE'], cid_info['CHAPTER']))
+
+ if not os.path.exists(save_path):
+ os.makedirs(save_path)
+
+ print(f'Saving chapter to {save_path}\n')
+
+ for page in range(1, len(meta['data']['result']) + 1):
+
+ if args.nolog:
+ if page == 1:
+ logging.info('DL in progress...')
+ else:
+ logging.info('Progress: page ' + str(page))
+
+ key = unhexlify(meta['data']['result'][page-1]['meta']['drm_hash'][:16])
+ enc = requests.get(meta['data']['result'][page-1]['meta']['source_url'], headers=headers).content
+ pagination = str(page) + '.webp'
+
+ with open(f'{save_path}\\{pagination}', 'wb') as f:
+ f.write(xor(enc, key))
+
+ logging.info('Done.')
+
+def xor(bin, key):
+ retval = []
+
+ for i in range(len(bin)):
+ retval.append(bin[i] ^ key[i % len(key)])
+
+ return bytes(retval)
+
+def main():
+
+ headers = {
+ 'authority': 'comicwalker-api.nicomanga.jp',
+ 'accept': '*/*',
+ 'accept-language': 'en-US,en;q=0.9',
+ 'cache-control': 'no-cache',
+ 'origin': 'https://comic-walker.com',
+ 'pragma': 'no-cache',
+ 'referer': 'https://comic-walker.com/',
+ 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-platform': '"Windows"',
+ 'sec-fetch-Blowfisht': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'cross-site',
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
+ }
+
+ content_url = f'https://comicwalker-api.nicomanga.jp/api/v1/comicwalker/episodes/{args.cid}'
+
+ start(content_url, headers)
+
+if __name__ == "__main__":
+ main() \ No newline at end of file