import requests
import jwt
import json
import time
import aiohttp
import asyncio
import os
import logging
logging.basicConfig(format="%(asctime)s [%(levelname)s]: %(message)s", level=logging.INFO)
class Wqxuetang():
def __init__(self, bookid, max_threads=4, interval=1):
self.bookid = bookid
self.max_threads = max_threads
self.interval = interval
self.work_queue = asyncio.Queue()
self.jwt_secret = "g0NnWdSE8qEjdMD8a1aq12qEYphwErKctvfd3IktWHWiOBpVsgkecur38aBRPn2w"
self.session = requests.session()
self.jwtkey = self.get_jwt_key()
self.timeoutlist = []
(self.bookname, self.totalpages) = self.bookinfo()
self.totalpages = int(self.totalpages)
self.creat_and_enter_book_dir()
def creat_and_enter_book_dir(self):
curpath = os.getcwd()
newpath = curpath + os.path.sep + self.bookname
os.mkdir(newpath)
os.chdir(newpath)
def bookinfo(self):
url = f"https://lib-nuanxin.wqxuetang.com/v1/read/initread?bid={self.bookid}"
r = self.session.get(url)
info = json.loads(r.text)
data = info['data']
return data['name'], data['canreadpages']
def get_jwt_key(self):
url = "https://lib-nuanxin.wqxuetang.com/v1/read/k?bid=%s" % self.bookid
r = self.session.get(url, timeout=5)
j = json.loads(r.text)
return j['data']
def get_jwt_token(self, page):
cur_time = time.time()
jwttoken = jwt.encode({
"p": page,
"t": int(cur_time)*1000,
"b": str(self.bookid),
"w": 1000,
"k": json.dumps(self.jwtkey),
"iat": int(cur_time)
}, self.jwt_secret, algorithm='HS256').decode('ascii')
return jwttoken
async def download_img(self, page, task_id):
token = self.get_jwt_token(page)
url = f"https://lib-nuanxin.wqxuetang.com/page/img/{self.bookid}/{page}?k={token}"
headers = {
'referer': f'https://lib-nuanxin.wqxuetang.com/read/pdf/{self.bookid}',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, timeout=5) as response:
r = await response.read()
except Exception:
logging.warning(f"线程 {task_id} -> 第 {page} 张下载失败, 重回队列!!!")
self.work_queue.put_nowait(page)
else:
if len(r) == 10400:
logging.warning(f"线程 {task_id} -> 第 {page} 张图片大小异常, 重回队列!!!")
self.work_queue.put_nowait(page)
else:
with open(f"{self.bookname+str(page)}.png", "wb") as f:
f.write(r)
logging.info(f"线程 {task_id} -> 第 {page} 张下载完成")
async def handle_tasks(self, task_id):
while not self.work_queue.empty():
page = await self.work_queue.get()
await self.download_img(page, task_id)
await asyncio.sleep(self.interval)
logging.info(f"线程 {task_id} 结束工作!~")
def main(self):
[self.work_queue.put_nowait(page) for page in range(1, self.totalpages + 1)]
loop = asyncio.get_event_loop()
tasks = [self.handle_tasks(task_id) for task_id in range(self.max_threads)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
if __name__ == "__main__":
bookid = 3208566
# 默认书名为下载文件夹名
# 参数1:书号, 参数2:线程数, 参数3:下载时间间隔
w = Wqxuetang(bookid, 3, 1)
w.main()