From c709c44f479b6a3f707a807973c23cb7404046fb Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 20:14:27 +0200 Subject: [PATCH 01/29] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 24ea2bc..61cc4f2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ -# booklead +# booklead 2.0 Утилита для загрузки книг из интернет-библиотек - +Весь кредит: https://github.com/aliasn3t. +Здесь лишь добавлена поддержка prlib.ru (1-2 секунды страница в лучшем качестве) и возможно ещё в скором времени. +## Еще сделать: +- Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) +- добавить возможность параллельно заранить на нескольких корах (parallelizaton) +- усокрить (возможно добавить asyncio ещё на некоторых местах) +------------ ## Поддерживаемые ресурсы: * elib.shpl.ru - электронная библиотека ГПИБ From 5d6b10004a1a54d965ee4b0d74a3c9eab81fc198 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 20:15:06 +0200 Subject: [PATCH 02/29] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit обновил Readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 61cc4f2..b92a670 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # booklead 2.0 -Утилита для загрузки книг из интернет-библиотек -Весь кредит: https://github.com/aliasn3t. +Утилита для загрузки книг из интернет-библиотек +Все уважение и заслуга: https://github.com/aliasn3t. Здесь лишь добавлена поддержка prlib.ru (1-2 секунды страница в лучшем качестве) и возможно ещё в скором времени. ## Еще сделать: - Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) From 3c9ab0efa078c72914aa51098162a1656b6dc541 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 20:17:24 +0200 Subject: [PATCH 03/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b92a670..4945c6d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # booklead 2.0 Утилита для загрузки книг из интернет-библиотек Все уважение и заслуга: https://github.com/aliasn3t. -Здесь лишь добавлена поддержка prlib.ru (1-2 секунды страница в лучшем качестве) и возможно ещё в скором времени. +Здесь лишь добавлена поддержка prlib.ru (1-2 секунды страница в лучшем качестве) и возможно ещё какие фичи в скором времени. ## Еще сделать: - Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) - добавить возможность параллельно заранить на нескольких корах (parallelizaton) From 42344ea023cb8179ab322ba1bb6074058d14108a Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 20:17:37 +0200 Subject: [PATCH 04/29] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4945c6d..dadf2d4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # booklead 2.0 Утилита для загрузки книг из интернет-библиотек -Все уважение и заслуга: https://github.com/aliasn3t. -Здесь лишь добавлена поддержка prlib.ru (1-2 секунды страница в лучшем качестве) и возможно ещё какие фичи в скором времени. +Все уважение и заслуга: https://github.com/aliasn3t. +Здесь лишь добавлена поддержка prlib.ru +(1-2 секунды страница в лучшем качестве) и возможно ещё какие фичи в скором времени. ## Еще сделать: - Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) - добавить возможность параллельно заранить на нескольких корах (parallelizaton) From d9ba9a0e3911c876e6aaf2690d102310e119c664 Mon Sep 17 00:00:00 2001 From: Me Date: Thu, 8 May 2025 20:53:20 +0200 Subject: [PATCH 05/29] Bookleads 2.0. Support for prlib.ru. 1-2 seconds/image. --- booklead.py | 90 +++++++++++++++++++++++++++++++++++++++--------- requirements.txt | 10 ++++-- util.py | 43 +++++++++++++++++++++-- 3 files changed, 122 insertions(+), 21 deletions(-) diff --git a/booklead.py b/booklead.py index 4c258af..5888d9c 100644 --- a/booklead.py +++ b/booklead.py @@ -4,13 +4,20 @@ import os import re import urllib.parse - +import asyncio +from aiohttp import ClientSession +import numpy as np +import nest_asyncio +from util import CV2_Russian, BinaryToDecimal,number_of_images, Postprocess +import cv2 +import random import img2pdf from bs4 import BeautifulSoup - +import sys from util import get_logger from util import md5_hex, to_float, cut_bom, perror, progress, ptext, safe_file_name, Browser, select_one_text_optional -from util import select_one_text_required, select_one_attr_required, gwar_fix_json +from util import select_one_text_required, select_one_attr_required, gwar_fix_json,mkdirs_for_regular_file +from util import user_agents log = get_logger(__name__) @@ -22,8 +29,8 @@ } prlDl_params = { - 'ext': 'jpg' -} + 'ext': 'jpg' } + bro: Browser @@ -48,25 +55,53 @@ def saveImage(url, img_id, folder, ext, referer): bro.download(url, image_path, headers, content_type=expected_ct, skip_if_file_exists=True) + +async def fetch_image(url: str, i,queue,headers): + async with ClientSession() as session: + async with session.get(url, headers=headers) as response: + result = (i, await response.read()) + await queue.put(result) + +async def async_images(url,num,headers): + global results_prlDl + results_prlDl=[] + + queue = asyncio.Queue() + headers = headers + headers.update({'User-Agent': random.choice(user_agents)}) + async with asyncio.TaskGroup() as group: + for i in range(num): + group.create_task(fetch_image(url.format(i), i,queue,headers)) + while not queue.empty(): + results_prlDl.append(await queue.get()) + + def eshplDl(url): ext = eshplDl_params['ext'] quality = eshplDl_params['quality'] domain = urllib.parse.urlsplit(url).netloc html_text = bro.get_text(url) + soup = BeautifulSoup(html_text, 'html.parser') title = select_one_text_optional(soup, 'title') or md5_hex(url) title = safe_file_name(title) + for script in soup.findAll('script'): + + st = str(script) + if 'initDocview' in st: book_json = json.loads(st[st.find('{"'): st.find(')')]) - ptext(f' ─ Каталог для загрузки: {title}') + #print("HERE") + ptext(f' Каталог для загрузки: {title}') + #print("HERE") pages = book_json['pages'] for idx, page in enumerate(pages): img_url = f'http://{domain}/pages/{page["id"]}/zooms/{quality}' saveImage(img_url, idx + 1, title, ext, url) - progress(f' ─ Прогресс: {idx + 1} из {len(pages)} стр.') + progress(f' Прогресс: {idx + 1} из {len(pages)} стр.') return title, ext @@ -81,20 +116,43 @@ def prlDl(url): soup = BeautifulSoup(html_text, 'html.parser') title = select_one_text_optional(soup, 'h1') or md5_hex(url) title = safe_file_name(title) - ptext(f' ─ Каталог для загрузки: {title}') + #sys.stdout.write(title) + ptext(f'Каталог для загрузки: {title}') + for script in soup.findAll('script'): st = str(script) if 'jQuery.extend' in st: book_json = json.loads(st[st.find('{"'): st.find(');')]) - book = book_json['diva']['1']['options'] + if "item" in url.split("prlib.ru/")[1]: #case for https://www.prlib.ru/item/*** + book = book_json['diva']['1']['options'] + elif "node" in url.split("prlib.ru/")[1]: #case for https://www.prlib.ru/node/*** + book = book_json['diva']['settings'] json_text = bro.get_text(book['objectData']) book_data = json.loads(json_text) pages = book_data['pgs'] for idx, page in enumerate(pages): - img_url = 'https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF={}/{}&WID={}&CVT=jpeg'.format( - book['imageDir'], page['f'], page['d'][len(page['d']) - 1]['w']) - saveImage(img_url, idx + 1, title, ext, url) - progress(f' ─ Прогресс: {idx + 1} из {len(pages)} стр.') + + img_url = 'https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF={}/{}&JTL={},'.format( + book['imageDir'], page['f'], page['m']) + img_url+="{}" + width, height=number_of_images(page["d"][len(page['d']) - 1]['w'],page["d"][len(page['d']) - 1]['h']) + + image_short = '%05d.%s' % (idx+1, ext) + image_path = os.path.join(BOOK_DIR, title, image_short) + + if os.path.exists(image_path) and os.stat(image_path).st_size > 0: + log.info(f'Пропускаю скачанный файл: {image_path}') + else: + mkdirs_for_regular_file(image_path) + headers = {'Referer': url} + nest_asyncio.apply() + asyncio.run(async_images(img_url,width*height,headers)) + global results_prlDl + + Postprocess(results_prlDl,width,height, image_path) + + + progress(f' Прогресс: {idx + 1} из {len(pages)} стр.') return title, ext @@ -192,7 +250,7 @@ def gwarDL(url): book_dir = ('{}_{}'.format(book_id, title))[0:224] - ptext(f' ─ Каталог для загрузки: {book_dir}') + ptext(f' Каталог для загрузки: {book_dir}') request_headers = {'referer': url} json_text = bro.post_text(json_url, request_headers, request_data) @@ -212,7 +270,7 @@ def gwarDL(url): img_url = 'https://cdn.gwar.mil.ru/imagesfww/{}'.format( # либо ...ru/imageloadfull/ image_url) saveImage(img_url, idx + 1, book_dir, ext, 'https://gwar.mil.ru/') - progress(f' ─ Прогресс: {idx + 1} из {len(pages)} стр.') + progress(f' Прогресс: {idx + 1} из {len(pages)} стр.') return title, ext @@ -271,7 +329,7 @@ def main(): for url in urls: load = download_book(url) if load and args.pdf.lower() in ['y', 'yes']: - progress(' ─ Создание PDF...') + progress(' Создание PDF...') title, img_ext = load img_folder_full = os.path.join(BOOK_DIR, title) pdf_path = os.path.join(BOOK_DIR, f'{title}.pdf') diff --git a/requirements.txt b/requirements.txt index 9f25d26..0266d10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,7 @@ -beautifulsoup4==4.9.0 -img2pdf==0.3.6 -requests==2.25.1 +aiohttp==3.9.5 +beautifulsoup4==4.13.4 +img2pdf==0.6.1 +nest_asyncio==1.6.0 +numpy==2.2.5 +opencv_python==4.11.0.86 +Requests==2.32.3 diff --git a/util.py b/util.py index 8f08a5e..2d2bfa9 100644 --- a/util.py +++ b/util.py @@ -5,13 +5,14 @@ import functools import hashlib import logging +import numpy as np import os import random import re import shutil import sys import time - +import cv2 import requests from bs4 import Tag from requests import Response @@ -90,7 +91,45 @@ def mkdirs_for_regular_file(filename: str): if e.errno != errno.EEXIST: raise - +def Postprocess(results_prlDl,width, height,image_path): + Total_Image=[i for i in range(len(results_prlDl))] + for item in results_prlDl: + Total_Image[item[0]]=BinaryToDecimal(item[1],os.path.dirname(image_path)) + + os.remove(os.path.join(os.path.dirname(image_path), "test.jpg")) + regroup=[] + for h in range(height): + regroup.append(Total_Image[h*width:(h+1)*width]) + im_h=cv2.vconcat([cv2.hconcat(item) for item in regroup]) + + #cv2.imwrite(image_path, im_h) (doesn't work with Russian) + result, data = cv2.imencode('.jpg', im_h) + fh = open(image_path, 'wb') + fh.write(data) + fh.close() +def number_of_images(width, height): + num_w=width//256 + if width%256!=0: + num_w+=1 + num_h=height//256 + if height%256!=0: + num_h+=1 + return int(num_w),int(num_h) + +def BinaryToDecimal(binary,image_path): + with open(os.path.join(image_path, "test.jpg"), "wb") as file: + file.write(binary) + dec=CV2_Russian(os.path.join(image_path, "test.jpg")) + return dec +def CV2_Russian(name): + #https://answers.opencv.org/question/205345/imread-and-russian-language-path-to-img/ + f = open(name, "rb") + chunk = f.read() + chunk_arr = np.frombuffer(chunk, dtype=np.uint8) + img = cv2.imdecode(chunk_arr, cv2.IMREAD_COLOR) + return img + + def cut_bom(s: str): bom = codecs.BOM_UTF8.decode("utf-8") return s[len(bom):] if s.startswith(bom) else s From b7b9f55e8599b40516ab9c95bc97d8812d841aa3 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 21:14:41 +0200 Subject: [PATCH 06/29] Delete README.md --- README.md | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index dadf2d4..0000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# booklead 2.0 -Утилита для загрузки книг из интернет-библиотек -Все уважение и заслуга: https://github.com/aliasn3t. -Здесь лишь добавлена поддержка prlib.ru -(1-2 секунды страница в лучшем качестве) и возможно ещё какие фичи в скором времени. -## Еще сделать: -- Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) -- добавить возможность параллельно заранить на нескольких корах (parallelizaton) -- усокрить (возможно добавить asyncio ещё на некоторых местах) ------------- -## Поддерживаемые ресурсы: - -* elib.shpl.ru - электронная библиотека ГПИБ -* docs.historyrussia.org - электронная библиотека исторических документов -* prlib.ru - президентская библиотека имени Б.Н. Ельцина -* elibrary.unatlib.ru - национальная электронная библиотека Удмуртской республики -* gwar.mil.ru - информационный портал о первой мировой войне 1914-1918 - -## Запуск - -Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) -Для запуска кода потребуется Python с модулями **img2pdf**, **requests** и **beautifulsoup4** -Установка модулей: `python3 -m pip install -r requirements.txt` - -## Использование - -`--list` загрузка книг по ссылкам из файла -Пример использования: `booklead --list books.txt` -Пример содержимого **books.txt**: -``` -https://www.prlib.ru/item/420931 -http://docs.historyrussia.org/ru/nodes/139435 -... -http://elib.shpl.ru/ru/nodes/16533-vyp-1-zhilischnoe-stroitelstvo-v-gorodskih-poseleniyah-rsfsr-ukrainskoy-ssr-i-belorusskoy-ssr-1927 -``` -`--url` загрузка одной книги по ссылке -Пример использования: `booklead --url https://www.prlib.ru/item/420931` -`--pdf` создание PDF-версий загружаемых книг -Пример использования: `booklead --list books.txt --pdf y` From dcbdc6201fdfc65db7ed01ad08f3712f88677290 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 21:16:06 +0200 Subject: [PATCH 07/29] Create README.md --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..24ea2bc --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# booklead +Утилита для загрузки книг из интернет-библиотек + +## Поддерживаемые ресурсы: + +* elib.shpl.ru - электронная библиотека ГПИБ +* docs.historyrussia.org - электронная библиотека исторических документов +* prlib.ru - президентская библиотека имени Б.Н. Ельцина +* elibrary.unatlib.ru - национальная электронная библиотека Удмуртской республики +* gwar.mil.ru - информационный портал о первой мировой войне 1914-1918 + +## Запуск + +Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) +Для запуска кода потребуется Python с модулями **img2pdf**, **requests** и **beautifulsoup4** +Установка модулей: `python3 -m pip install -r requirements.txt` + +## Использование + +`--list` загрузка книг по ссылкам из файла +Пример использования: `booklead --list books.txt` +Пример содержимого **books.txt**: +``` +https://www.prlib.ru/item/420931 +http://docs.historyrussia.org/ru/nodes/139435 +... +http://elib.shpl.ru/ru/nodes/16533-vyp-1-zhilischnoe-stroitelstvo-v-gorodskih-poseleniyah-rsfsr-ukrainskoy-ssr-i-belorusskoy-ssr-1927 +``` +`--url` загрузка одной книги по ссылке +Пример использования: `booklead --url https://www.prlib.ru/item/420931` +`--pdf` создание PDF-версий загружаемых книг +Пример использования: `booklead --list books.txt --pdf y` From 2e6b839191605e5299dc97df6444c1833a4d1cdc Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 22:01:02 +0200 Subject: [PATCH 08/29] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 24ea2bc..ebc178a 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ ## Запуск Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) -Для запуска кода потребуется Python с модулями **img2pdf**, **requests** и **beautifulsoup4** +Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **nest_asyncio**, **numpy** и **opencv_python**. + Установка модулей: `python3 -m pip install -r requirements.txt` ## Использование From 70a42a1bfc54b01788bfe072b43cceaf1ef64629 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 22:09:57 +0200 Subject: [PATCH 09/29] Update util.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавил комменты --- util.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/util.py b/util.py index 2d2bfa9..4516a44 100644 --- a/util.py +++ b/util.py @@ -92,6 +92,9 @@ def mkdirs_for_regular_file(filename: str): raise def Postprocess(results_prlDl,width, height,image_path): + """ + Прохожу через бинарные данные в results_prlDl, ставлю их на правильные места в картинке исходной и вывожу все в файл, напртмер 0001.jpg + """ Total_Image=[i for i in range(len(results_prlDl))] for item in results_prlDl: Total_Image[item[0]]=BinaryToDecimal(item[1],os.path.dirname(image_path)) @@ -108,6 +111,9 @@ def Postprocess(results_prlDl,width, height,image_path): fh.write(data) fh.close() def number_of_images(width, height): + """ + получаю кол-во картинок по ширине и длине (возможно можно в одну строчку как-то:) + """ num_w=width//256 if width%256!=0: num_w+=1 @@ -117,12 +123,18 @@ def number_of_images(width, height): return int(num_w),int(num_h) def BinaryToDecimal(binary,image_path): + """ + тупой вариант перевода binary в decimal для картинки. остальные способы казались слишком) + """ with open(os.path.join(image_path, "test.jpg"), "wb") as file: file.write(binary) - dec=CV2_Russian(os.path.join(image_path, "test.jpg")) + dec=CV2_Russian(os.path.join(image_path, "test.jpg")) # название папки на Русском в названии мешало прочитать cv2 файл (это окалаось известный баг cv2) return dec def CV2_Russian(name): + """ + Чтение картинки с русским названием в пути в cv2 #https://answers.opencv.org/question/205345/imread-and-russian-language-path-to-img/ + """ f = open(name, "rb") chunk = f.read() chunk_arr = np.frombuffer(chunk, dtype=np.uint8) From 2a8481b49e9fa26b92b4529a55d99537e7420fbd Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 22:19:14 +0200 Subject: [PATCH 10/29] Update booklead.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Закомментил все изменения --- booklead.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/booklead.py b/booklead.py index 5888d9c..d4a965b 100644 --- a/booklead.py +++ b/booklead.py @@ -57,12 +57,18 @@ def saveImage(url, img_id, folder, ext, referer): async def fetch_image(url: str, i,queue,headers): + """ Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) + по url скачиваю картинку и добавляю в binary в queue asyncio + """ async with ClientSession() as session: async with session.get(url, headers=headers) as response: result = (i, await response.read()) await queue.put(result) async def async_images(url,num,headers): + """Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) + call every tile image to download in async mode (in the end, add binary with the image number to results_prlDl + """ global results_prlDl results_prlDl=[] @@ -116,7 +122,6 @@ def prlDl(url): soup = BeautifulSoup(html_text, 'html.parser') title = select_one_text_optional(soup, 'h1') or md5_hex(url) title = safe_file_name(title) - #sys.stdout.write(title) ptext(f'Каталог для загрузки: {title}') for script in soup.findAll('script'): @@ -133,22 +138,26 @@ def prlDl(url): for idx, page in enumerate(pages): img_url = 'https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF={}/{}&JTL={},'.format( - book['imageDir'], page['f'], page['m']) + book['imageDir'], page['f'], page['m']) #поменял здесь немного вид урл, так как по частям качаю + # брал урл отсюда: https://iipimage.sourceforge.io/documentation/protocol img_url+="{}" width, height=number_of_images(page["d"][len(page['d']) - 1]['w'],page["d"][len(page['d']) - 1]['h']) image_short = '%05d.%s' % (idx+1, ext) image_path = os.path.join(BOOK_DIR, title, image_short) - + + # заменяю все фичи ручками (например тут skip_if_exists), которые были ранее доступны через функции + #(т.к. метод у меня скачивания немного другой) if os.path.exists(image_path) and os.stat(image_path).st_size > 0: log.info(f'Пропускаю скачанный файл: {image_path}') else: mkdirs_for_regular_file(image_path) headers = {'Referer': url} - nest_asyncio.apply() + nest_asyncio.apply() # нужен только чтобы async работал нормально ( https://pypi.org/project/nest-asyncio/) + # получить все данные с картиники asyncio.run(async_images(img_url,width*height,headers)) global results_prlDl - + # просессить все данные и в конце вывести картинку Postprocess(results_prlDl,width,height, image_path) From 2e96e8d05b23765930d6e265e9f8de6be48b3773 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 22:21:04 +0200 Subject: [PATCH 11/29] Update booklead.py --- booklead.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/booklead.py b/booklead.py index d4a965b..8363120 100644 --- a/booklead.py +++ b/booklead.py @@ -100,9 +100,7 @@ def eshplDl(url): if 'initDocview' in st: book_json = json.loads(st[st.find('{"'): st.find(')')]) - #print("HERE") ptext(f' Каталог для загрузки: {title}') - #print("HERE") pages = book_json['pages'] for idx, page in enumerate(pages): img_url = f'http://{domain}/pages/{page["id"]}/zooms/{quality}' From 645d3cc68b9996382c6a1d06c88f3c9e7212b575 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 22:50:12 +0200 Subject: [PATCH 12/29] Update booklead.py --- booklead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/booklead.py b/booklead.py index 8363120..97b8f54 100644 --- a/booklead.py +++ b/booklead.py @@ -122,7 +122,7 @@ def prlDl(url): title = safe_file_name(title) ptext(f'Каталог для загрузки: {title}') - for script in soup.findAll('script'): + for script in soup.find_all('script'): #findAll deprecated st = str(script) if 'jQuery.extend' in st: book_json = json.loads(st[st.find('{"'): st.find(');')]) From db7d5323a9f2da56407536fc1f7076d2e02203fc Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Thu, 8 May 2025 22:59:40 +0200 Subject: [PATCH 13/29] Update booklead.py --- booklead.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/booklead.py b/booklead.py index 97b8f54..5f78c15 100644 --- a/booklead.py +++ b/booklead.py @@ -66,9 +66,9 @@ async def fetch_image(url: str, i,queue,headers): await queue.put(result) async def async_images(url,num,headers): - """Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) - call every tile image to download in async mode (in the end, add binary with the image number to results_prlDl - """ + """Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) + call every tile image to download in async mode (in the end, add binary with the image number to results_prlDl + """ global results_prlDl results_prlDl=[] From 45bc6987767b42f25def54750215df0bcc38d6f8 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Fri, 9 May 2025 01:28:12 +0200 Subject: [PATCH 14/29] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0266d10..df06dd0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,6 @@ aiohttp==3.9.5 beautifulsoup4==4.13.4 img2pdf==0.6.1 nest_asyncio==1.6.0 -numpy==2.2.5 +numpy==1.26.4 opencv_python==4.11.0.86 Requests==2.32.3 From db7056f30591fa16a376583f0533a7b69e365d6c Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Fri, 9 May 2025 21:26:48 +0200 Subject: [PATCH 15/29] Update util.py solved warning --- util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.py b/util.py index 4516a44..02bbd83 100644 --- a/util.py +++ b/util.py @@ -166,7 +166,7 @@ def gwar_fix_json(s: str, a: bool = False) -> str: s = s.replace("'", '"') if a: # https://stackoverflow.com/questions/50947760/how-to-fix-json-key-values-without-double-quotes - s = re.sub("(\w+):", r'"\1":', s) + s = re.sub(r"(\w+):", r'"\1":', s) #added r: https://stackoverflow.com/questions/50504500/deprecationwarning-invalid-escape-sequence-what-to-use-instead-of-d json_s = json.loads(s) return json_s From 462076201bf81475278a5389cc06b910a214da9f Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Fri, 9 May 2025 23:41:14 +0200 Subject: [PATCH 16/29] Update booklead.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавил предсказатель времени --- booklead.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/booklead.py b/booklead.py index 5f78c15..efc0a67 100644 --- a/booklead.py +++ b/booklead.py @@ -6,9 +6,10 @@ import urllib.parse import asyncio from aiohttp import ClientSession +import datetime import numpy as np import nest_asyncio -from util import CV2_Russian, BinaryToDecimal,number_of_images, Postprocess +from util import CV2_Russian, BinaryToDecimal,number_of_images, Postprocess, Time_Processing import cv2 import random import img2pdf @@ -133,6 +134,8 @@ def prlDl(url): json_text = bro.get_text(book['objectData']) book_data = json.loads(json_text) pages = book_data['pgs'] + num_of_pages_down=0 #for the time prediction + start=datetime.datetime.now()#for the time prediction for idx, page in enumerate(pages): img_url = 'https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF={}/{}&JTL={},'.format( @@ -148,6 +151,7 @@ def prlDl(url): #(т.к. метод у меня скачивания немного другой) if os.path.exists(image_path) and os.stat(image_path).st_size > 0: log.info(f'Пропускаю скачанный файл: {image_path}') + progress(f' Прогресс: {idx + 1} из {len(pages)} стр. ') else: mkdirs_for_regular_file(image_path) headers = {'Referer': url} @@ -157,9 +161,13 @@ def prlDl(url): global results_prlDl # просессить все данные и в конце вывести картинку Postprocess(results_prlDl,width,height, image_path) - - - progress(f' Прогресс: {idx + 1} из {len(pages)} стр.') + # Time Formatting/Prediction: + prog=datetime.datetime.now()-start + num_of_pages_down+=1 + left=prog/num_of_pages_down*(len(pages)-(idx+1)) #based on the values before prediction + minutes, seconds = Time_Processing(left) + past_min, past_sec=Time_Processing(prog) + progress(f' Прогресс: {idx + 1} из {len(pages)} стр. | Прошло (мин:сек): {past_min}:{past_sec} ;Осталось: {minutes}:{seconds} ') return title, ext From 60f30e6c2b709e1c08719e224fc6a787b12964e0 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Fri, 9 May 2025 23:42:01 +0200 Subject: [PATCH 17/29] Update util.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Утилиты для времени --- util.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/util.py b/util.py index 02bbd83..c1b9929 100644 --- a/util.py +++ b/util.py @@ -12,6 +12,7 @@ import shutil import sys import time +import datetime import cv2 import requests from bs4 import Tag @@ -90,7 +91,11 @@ def mkdirs_for_regular_file(filename: str): except OSError as e: # Guard against race condition if e.errno != errno.EEXIST: raise - +def Time_Processing(timedelta): + """Чтоб время показывать + """ + minutes, seconds = divmod(round(timedelta.total_seconds()), 60) + return minutes, seconds def Postprocess(results_prlDl,width, height,image_path): """ Прохожу через бинарные данные в results_prlDl, ставлю их на правильные места в картинке исходной и вывожу все в файл, напртмер 0001.jpg From 28ef27bda26e1f72087271686c8867a1336eb53c Mon Sep 17 00:00:00 2001 From: Me Date: Sat, 10 May 2025 10:27:45 +0200 Subject: [PATCH 18/29] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D0=B5=D0=BA=D1=83=D0=BD=D0=B4=D1=8B=20=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20Python=203.11.11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- booklead.py | 2 +- requirements.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/booklead.py b/booklead.py index efc0a67..96e3515 100644 --- a/booklead.py +++ b/booklead.py @@ -167,7 +167,7 @@ def prlDl(url): left=prog/num_of_pages_down*(len(pages)-(idx+1)) #based on the values before prediction minutes, seconds = Time_Processing(left) past_min, past_sec=Time_Processing(prog) - progress(f' Прогресс: {idx + 1} из {len(pages)} стр. | Прошло (мин:сек): {past_min}:{past_sec} ;Осталось: {minutes}:{seconds} ') + progress(f' Прогресс: {idx + 1} из {len(pages)} стр. | Прошло (мин:сек): {past_min}:{past_sec:02d} ;Осталось: {minutes}:{seconds:02d} ') return title, ext diff --git a/requirements.txt b/requirements.txt index df06dd0..d74ca90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,7 @@ aiohttp==3.9.5 beautifulsoup4==4.13.4 img2pdf==0.6.1 nest_asyncio==1.6.0 -numpy==1.26.4 +numpy==2.2.5 opencv_python==4.11.0.86 Requests==2.32.3 +pillow==11.2.1 \ No newline at end of file From 5506d706b850d187cda5efe01d6a487039791b9b Mon Sep 17 00:00:00 2001 From: Me Date: Sat, 10 May 2025 11:37:08 +0200 Subject: [PATCH 19/29] Exceptions of asyncio --- booklead.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/booklead.py b/booklead.py index 96e3515..c57784c 100644 --- a/booklead.py +++ b/booklead.py @@ -57,7 +57,7 @@ def saveImage(url, img_id, folder, ext, referer): -async def fetch_image(url: str, i,queue,headers): +async def fetch_image(url: str, i,queue, headers): """ Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) по url скачиваю картинку и добавляю в binary в queue asyncio """ @@ -65,20 +65,18 @@ async def fetch_image(url: str, i,queue,headers): async with session.get(url, headers=headers) as response: result = (i, await response.read()) await queue.put(result) - + async def async_images(url,num,headers): """Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) call every tile image to download in async mode (in the end, add binary with the image number to results_prlDl """ - global results_prlDl - results_prlDl=[] - + queue = asyncio.Queue() - headers = headers - headers.update({'User-Agent': random.choice(user_agents)}) async with asyncio.TaskGroup() as group: for i in range(num): group.create_task(fetch_image(url.format(i), i,queue,headers)) + global results_prlDl + results_prlDl=[] while not queue.empty(): results_prlDl.append(await queue.get()) @@ -108,7 +106,7 @@ def eshplDl(url): saveImage(img_url, idx + 1, title, ext, url) progress(f' Прогресс: {idx + 1} из {len(pages)} стр.') return title, ext - + def prlDl(url): """ @@ -136,6 +134,7 @@ def prlDl(url): pages = book_data['pgs'] num_of_pages_down=0 #for the time prediction start=datetime.datetime.now()#for the time prediction + headers = {'Referer': url} for idx, page in enumerate(pages): img_url = 'https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF={}/{}&JTL={},'.format( @@ -154,13 +153,15 @@ def prlDl(url): progress(f' Прогресс: {idx + 1} из {len(pages)} стр. ') else: mkdirs_for_regular_file(image_path) - headers = {'Referer': url} - nest_asyncio.apply() # нужен только чтобы async работал нормально ( https://pypi.org/project/nest-asyncio/) + #nest_asyncio.apply() # нужен только чтобы async работал нормально в Jupyter ( https://pypi.org/project/nest-asyncio/) # получить все данные с картиники + headers.update({'User-Agent': random.choice(user_agents)}) asyncio.run(async_images(img_url,width*height,headers)) + global results_prlDl # просессить все данные и в конце вывести картинку Postprocess(results_prlDl,width,height, image_path) + # Time Formatting/Prediction: prog=datetime.datetime.now()-start num_of_pages_down+=1 From 662f2e2ec9ce595baaae36fcbe1f7426d63f8e86 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sat, 10 May 2025 11:57:38 +0200 Subject: [PATCH 20/29] Update README.md --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ebc178a..bcb7567 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ -# booklead -Утилита для загрузки книг из интернет-библиотек - +# booklead 2.0 +Утилита для загрузки книг из интернет-библиотек +Все уважение и заслуга: https://github.com/aliasn3t. +Здесь лишь добавлена поддержка prlib.ru +(1-2 секунды страница в лучшем качестве) и возможно ещё какие фичи в скором времени. +## Еще сделать: +- Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) +- добавить возможность параллельно заранить на нескольких корах (parallelizaton) +- усокрить (возможно добавить asyncio ещё на некоторых местах) +------------ ## Поддерживаемые ресурсы: * elib.shpl.ru - электронная библиотека ГПИБ @@ -10,10 +17,9 @@ * gwar.mil.ru - информационный портал о первой мировой войне 1914-1918 ## Запуск - +Все проверял на Python 3.11.11. Если запускаете не через бинарник, советую запускать в [virtualenv](https://docs.python.org/3/library/venv.html). Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **nest_asyncio**, **numpy** и **opencv_python**. - Установка модулей: `python3 -m pip install -r requirements.txt` ## Использование From 03b020c9b886492e61bb7630c5e8aa6adb50afa5 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sat, 10 May 2025 12:21:44 +0200 Subject: [PATCH 21/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bcb7567..29a4bac 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ ## Запуск Все проверял на Python 3.11.11. Если запускаете не через бинарник, советую запускать в [virtualenv](https://docs.python.org/3/library/venv.html). -Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) + Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **nest_asyncio**, **numpy** и **opencv_python**. Установка модулей: `python3 -m pip install -r requirements.txt` From ffc21a04589922727098a51edcebc432ee3f9ca4 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sat, 10 May 2025 12:22:19 +0200 Subject: [PATCH 22/29] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 29a4bac..f35496d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ * gwar.mil.ru - информационный портал о первой мировой войне 1914-1918 ## Запуск -Все проверял на Python 3.11.11. Если запускаете не через бинарник, советую запускать в [virtualenv](https://docs.python.org/3/library/venv.html). +Все проверял на Python 3.11.11. советую запускать в [virtualenv](https://docs.python.org/3/library/venv.html). +Бинарника пока не сделал, делаю... Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **nest_asyncio**, **numpy** и **opencv_python**. Установка модулей: `python3 -m pip install -r requirements.txt` From d1ab85784ef42589797788ca77f8037c4b8154de Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sat, 10 May 2025 12:23:42 +0200 Subject: [PATCH 23/29] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f35496d..4e35703 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # booklead 2.0 Утилита для загрузки книг из интернет-библиотек Все уважение и заслуга: https://github.com/aliasn3t. -Здесь лишь добавлена поддержка prlib.ru -(1-2 секунды страница в лучшем качестве) и возможно ещё какие фичи в скором времени. +## Добавленные фичи: +- поддержка prlib.ru + - (1-2 секунды страница в лучшем качестве) + - индикатор времени ## Еще сделать: - Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) - добавить возможность параллельно заранить на нескольких корах (parallelizaton) From 81193296c6bbfcb041328071f68f4db5e5546f16 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sat, 10 May 2025 12:24:27 +0200 Subject: [PATCH 24/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e35703..76cbd5a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ - поддержка prlib.ru - (1-2 секунды страница в лучшем качестве) - индикатор времени -## Еще сделать: +## To-Do (в разработке): - Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) - добавить возможность параллельно заранить на нескольких корах (parallelizaton) - усокрить (возможно добавить asyncio ещё на некоторых местах) From 11df598267e915e32f82393ce41376c4e4e301e2 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sun, 11 May 2025 16:24:45 +0200 Subject: [PATCH 25/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76cbd5a..7bc4bb1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## To-Do (в разработке): - Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) - добавить возможность параллельно заранить на нескольких корах (parallelizaton) -- усокрить (возможно добавить asyncio ещё на некоторых местах) +- усокрить (возможно добавить asyncio ещё на некоторых местах -для других библиотек) ------------ ## Поддерживаемые ресурсы: From 0f2c6779214ffbdfa6302b5003032085b3d2a740 Mon Sep 17 00:00:00 2001 From: Me Date: Sun, 11 May 2025 16:28:50 +0200 Subject: [PATCH 26/29] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D1=83=20=D1=81=20SSL?= =?UTF-8?q?=20connection.=20=D0=9E=D1=82=D0=BB=D0=B0=D0=B4=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BD=D0=B5=D1=82=D0=B2=D0=BE=D0=BA=D1=80=D0=B8=D0=BD=D0=B3.?= =?UTF-8?q?=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BE=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=B0=20request=20-=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BF=D0=B0=D1=80=D0=BE=D1=87=D0=BA=D1=83=20=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D1=85=20user=20agents=20-=20=D0=BE=D0=B1?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D0=B8=20(=D0=B2=D1=81=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=20=D0=BD=D0=B0=20Python=203.12.10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- booklead.py | 80 ++++++++++++++++++++++++++++++++++-------------- requirements.txt | 3 +- util.py | 3 ++ 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/booklead.py b/booklead.py index c57784c..fb63b24 100644 --- a/booklead.py +++ b/booklead.py @@ -5,10 +5,11 @@ import re import urllib.parse import asyncio -from aiohttp import ClientSession +from aiohttp import ClientSession,TCPConnector, ClientTimeout import datetime +import time import numpy as np -import nest_asyncio +#import nest_asyncio #used for debugging from util import CV2_Russian, BinaryToDecimal,number_of_images, Postprocess, Time_Processing import cv2 import random @@ -19,7 +20,7 @@ from util import md5_hex, to_float, cut_bom, perror, progress, ptext, safe_file_name, Browser, select_one_text_optional from util import select_one_text_required, select_one_attr_required, gwar_fix_json,mkdirs_for_regular_file from util import user_agents - +import logging log = get_logger(__name__) BOOK_DIR = 'books' @@ -31,7 +32,25 @@ prlDl_params = { 'ext': 'jpg' } - + +headers_pr1 = { + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Accept-Language': 'en-US,en;q=0.9', + 'Cache-Control': 'max-age=0', + 'Connection': 'keep-alive', + 'If-Modified-Since': 'Tue, 20 Dec 2016 02:17:59 GMT', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36', + 'dnt': '1', + 'sec-ch-ua': '"Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'sec-gpc': '1', +} bro: Browser @@ -55,32 +74,33 @@ def saveImage(url, img_id, folder, ext, referer): expected_ct = re.compile('image/') bro.download(url, image_path, headers, content_type=expected_ct, skip_if_file_exists=True) - - -async def fetch_image(url: str, i,queue, headers): +async def fetch_image(url: str, i,queue, headers_pr1, sem): """ Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) по url скачиваю картинку и добавляю в binary в queue asyncio """ - async with ClientSession() as session: - async with session.get(url, headers=headers) as response: - result = (i, await response.read()) - await queue.put(result) - -async def async_images(url,num,headers): + async with sem: + async with ClientSession(headers=headers_pr1,timeout=ClientTimeout(total=5),trust_env=True) as session: #,trust_env=True + async with session.get(url) as response: + result = (i, await response.read()) + await queue.put(result) + +async def async_images(url,num,headers_pr1): """Не добавляйте в util.py, у меня тогда asyncio не работал (может баг на моей стороне) call every tile image to download in async mode (in the end, add binary with the image number to results_prlDl """ - + + sem = asyncio.Semaphore(100)##https://stackoverflow.com/questions/63347818/aiohttp-client-exceptions-clientconnectorerror-cannot-connect-to-host-stackover queue = asyncio.Queue() - async with asyncio.TaskGroup() as group: + async with asyncio.TaskGroup() as group: #https://blog.csdn.net/y662225dd/article/details/135273140 for i in range(num): - group.create_task(fetch_image(url.format(i), i,queue,headers)) + headers_pr1.update({'User-Agent': random.choice(user_agents)}) + group.create_task(fetch_image(url.format(i), i,queue,headers_pr1,sem)) + global results_prlDl results_prlDl=[] while not queue.empty(): results_prlDl.append(await queue.get()) - - + def eshplDl(url): ext = eshplDl_params['ext'] quality = eshplDl_params['quality'] @@ -134,7 +154,6 @@ def prlDl(url): pages = book_data['pgs'] num_of_pages_down=0 #for the time prediction start=datetime.datetime.now()#for the time prediction - headers = {'Referer': url} for idx, page in enumerate(pages): img_url = 'https://content.prlib.ru/fcgi-bin/iipsrv.fcgi?FIF={}/{}&JTL={},'.format( @@ -154,11 +173,26 @@ def prlDl(url): else: mkdirs_for_regular_file(image_path) #nest_asyncio.apply() # нужен только чтобы async работал нормально в Jupyter ( https://pypi.org/project/nest-asyncio/) - # получить все данные с картиники - headers.update({'User-Agent': random.choice(user_agents)}) - asyncio.run(async_images(img_url,width*height,headers)) - + # получить все данные с картиники: + global headers_pr1 + headers_pr1.update({'Referer': url}) + + flag=True #для проверки на хороший requests global results_prlDl + while flag: #just keep quering the connection + try: + + asyncio.run(async_images(img_url,width*height,headers_pr1)) #Downgrade to 3.6.2 #Using Python 3.8 https://blog.csdn.net/y662225dd/article/details/135273140 + #loop = asyncio.get_event_loop() #for old version of aiohttp: 3.6.2 + #loop.run_until_complete(async_images(img_url,width*height,headers)) + except Exception as Argument: #Error coding + time.sleep(1.0) + + logging.exception("Error occurred in ASYNCIO") + else: + if len(results_prlDl)!=0: + flag=False + # просессить все данные и в конце вывести картинку Postprocess(results_prlDl,width,height, image_path) diff --git a/requirements.txt b/requirements.txt index d74ca90..53e8015 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ -aiohttp==3.9.5 +aiohttp==3.11.18 beautifulsoup4==4.13.4 img2pdf==0.6.1 -nest_asyncio==1.6.0 numpy==2.2.5 opencv_python==4.11.0.86 Requests==2.32.3 diff --git a/util.py b/util.py index c1b9929..44fe5f5 100644 --- a/util.py +++ b/util.py @@ -20,6 +20,7 @@ from typing import Dict, Optional, Pattern, Union import json + user_agents = [ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36', @@ -29,6 +30,7 @@ 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0' + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36' ] @@ -96,6 +98,7 @@ def Time_Processing(timedelta): """ minutes, seconds = divmod(round(timedelta.total_seconds()), 60) return minutes, seconds + def Postprocess(results_prlDl,width, height,image_path): """ Прохожу через бинарные данные в results_prlDl, ставлю их на правильные места в картинке исходной и вывожу все в файл, напртмер 0001.jpg From 827713fc9d08ec67c836204cff555583f94fef77 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sun, 11 May 2025 16:38:49 +0200 Subject: [PATCH 27/29] Delete README.md --- README.md | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 7bc4bb1..0000000 --- a/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# booklead 2.0 -Утилита для загрузки книг из интернет-библиотек -Все уважение и заслуга: https://github.com/aliasn3t. -## Добавленные фичи: -- поддержка prlib.ru - - (1-2 секунды страница в лучшем качестве) - - индикатор времени -## To-Do (в разработке): -- Оптимизировать PDF? (сейчас средний размер порядка 100 MB, с хорошей оптимизацией можно достичь 20) (отсюда например https://github.com/pts/pdfsizeopt) -- добавить возможность параллельно заранить на нескольких корах (parallelizaton) -- усокрить (возможно добавить asyncio ещё на некоторых местах -для других библиотек) ------------- -## Поддерживаемые ресурсы: - -* elib.shpl.ru - электронная библиотека ГПИБ -* docs.historyrussia.org - электронная библиотека исторических документов -* prlib.ru - президентская библиотека имени Б.Н. Ельцина -* elibrary.unatlib.ru - национальная электронная библиотека Удмуртской республики -* gwar.mil.ru - информационный портал о первой мировой войне 1914-1918 - -## Запуск -Все проверял на Python 3.11.11. советую запускать в [virtualenv](https://docs.python.org/3/library/venv.html). -Бинарника пока не сделал, делаю... - -Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **nest_asyncio**, **numpy** и **opencv_python**. -Установка модулей: `python3 -m pip install -r requirements.txt` - -## Использование - -`--list` загрузка книг по ссылкам из файла -Пример использования: `booklead --list books.txt` -Пример содержимого **books.txt**: -``` -https://www.prlib.ru/item/420931 -http://docs.historyrussia.org/ru/nodes/139435 -... -http://elib.shpl.ru/ru/nodes/16533-vyp-1-zhilischnoe-stroitelstvo-v-gorodskih-poseleniyah-rsfsr-ukrainskoy-ssr-i-belorusskoy-ssr-1927 -``` -`--url` загрузка одной книги по ссылке -Пример использования: `booklead --url https://www.prlib.ru/item/420931` -`--pdf` создание PDF-версий загружаемых книг -Пример использования: `booklead --list books.txt --pdf y` From 1c310a4bd7c949b84c2087ac3ed9c582a3242490 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sun, 11 May 2025 16:40:48 +0200 Subject: [PATCH 28/29] Create README.md --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..23cad11 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# booklead +Утилита для загрузки книг из интернет-библиотек + +## Поддерживаемые ресурсы: + +* elib.shpl.ru - электронная библиотека ГПИБ +* docs.historyrussia.org - электронная библиотека исторических документов +* prlib.ru - президентская библиотека имени Б.Н. Ельцина +* elibrary.unatlib.ru - национальная электронная библиотека Удмуртской республики +* gwar.mil.ru - информационный портал о первой мировой войне 1914-1918 + +## Запуск + +Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) +Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **numpy**, **opencv_python** и **pillow**. + +Установка модулей: `python3 -m pip install -r requirements.txt` + +## Использование + +`--list` загрузка книг по ссылкам из файла +Пример использования: `booklead --list books.txt` +Пример содержимого **books.txt**: +``` +https://www.prlib.ru/item/420931 +http://docs.historyrussia.org/ru/nodes/139435 +... +http://elib.shpl.ru/ru/nodes/16533-vyp-1-zhilischnoe-stroitelstvo-v-gorodskih-poseleniyah-rsfsr-ukrainskoy-ssr-i-belorusskoy-ssr-1927 +``` +`--url` загрузка одной книги по ссылке +Пример использования: `booklead --url https://www.prlib.ru/item/420931` +`--pdf` создание PDF-версий загружаемых книг +Пример использования: `booklead --list books.txt --pdf y` From 669018252894bbcac7e6007c3ef8e91211a46215 Mon Sep 17 00:00:00 2001 From: Andrey Vasenin <99732328+andrey-09@users.noreply.github.com> Date: Sun, 11 May 2025 17:37:20 +0200 Subject: [PATCH 29/29] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23cad11..08cf230 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ## Запуск -Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/aliasn3t/booklead/releases) +Для **Windows** доступны бинарные сборки в разделе [Releases](https://github.com/andrey-09/booklead_2.0/releases) Для запуска кода потребуется Python с модулями **img2pdf**, **requests**, **beautifulsoup4**, **aiohttp**, **img2pdf**, **numpy**, **opencv_python** и **pillow**. Установка модулей: `python3 -m pip install -r requirements.txt`