cobweb-launcher 3.1.36__py3-none-any.whl → 3.1.38__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cobweb/base/request.py +60 -38
- {cobweb_launcher-3.1.36.dist-info → cobweb_launcher-3.1.38.dist-info}/METADATA +1 -1
- {cobweb_launcher-3.1.36.dist-info → cobweb_launcher-3.1.38.dist-info}/RECORD +6 -6
- {cobweb_launcher-3.1.36.dist-info → cobweb_launcher-3.1.38.dist-info}/LICENSE +0 -0
- {cobweb_launcher-3.1.36.dist-info → cobweb_launcher-3.1.38.dist-info}/WHEEL +0 -0
- {cobweb_launcher-3.1.36.dist-info → cobweb_launcher-3.1.38.dist-info}/top_level.txt +0 -0
cobweb/base/request.py
CHANGED
@@ -440,12 +440,31 @@ class Request:
|
|
440
440
|
|
441
441
|
return result
|
442
442
|
|
443
|
+
def _log_download_progress(self, start_time, downloaded):
|
444
|
+
try:
|
445
|
+
elapsed_time = time.time() - start_time
|
446
|
+
elapsed_time_str = time.strftime("%H:%M:%S", time.gmtime(elapsed_time))
|
447
|
+
progress = downloaded / self.content_length
|
448
|
+
downloaded_mb = downloaded / (1024 * 1024)
|
449
|
+
total_mb = self.content_length / (1024 * 1024)
|
450
|
+
speed = downloaded / elapsed_time / 1024
|
451
|
+
filled_length = int(50 * progress)
|
452
|
+
bar = '█' * filled_length + '-' * (50 - filled_length)
|
453
|
+
logging.info(
|
454
|
+
f"\n\r\rDownloading {self.url}: |{bar}| {progress * 100:.1f}% "
|
455
|
+
f"{downloaded_mb:.1f}/{total_mb:.1f} MB [Time:{elapsed_time_str}, Speed {speed:.2f} KB/s]"
|
456
|
+
)
|
457
|
+
except Exception:
|
458
|
+
pass
|
459
|
+
|
443
460
|
def range_download(self, start: int = 0, chunk_size: int = 1024, file_type_detect: bool = True):
|
444
461
|
# 分块下载
|
445
462
|
downloaded = start
|
446
463
|
retry_count = 0
|
447
464
|
max_retries = 3
|
448
465
|
|
466
|
+
start_time = time.time()
|
467
|
+
|
449
468
|
detect_settings = self.request_settings.copy()
|
450
469
|
detect_settings.pop('stream', None)
|
451
470
|
|
@@ -469,33 +488,38 @@ class Request:
|
|
469
488
|
_start = downloaded
|
470
489
|
_end = min(downloaded + chunk_size - 1, self.content_length - 1)
|
471
490
|
detect_settings.setdefault("headers", {})['Range'] = f"bytes={_start}-{_end}"
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
491
|
+
try:
|
492
|
+
|
493
|
+
self.response = requests.request(
|
494
|
+
method=self.method,
|
495
|
+
url=self.url,
|
496
|
+
**detect_settings
|
497
|
+
)
|
498
|
+
|
499
|
+
if self.response.status_code == 206:
|
500
|
+
chunk_data = self.response.content
|
501
|
+
yield chunk_data
|
502
|
+
downloaded += len(chunk_data)
|
503
|
+
retry_count = 0 # 重置重试计数
|
504
|
+
self._log_download_progress(
|
505
|
+
start_time=start_time,
|
506
|
+
downloaded=downloaded
|
507
|
+
)
|
508
|
+
elif self.response.status_code == 416: # Range Not Satisfiable
|
509
|
+
logging.info("Range请求超出范围")
|
510
|
+
break
|
511
|
+
|
512
|
+
except Exception as e:
|
513
|
+
logging.exception(f"请求失败 - URL: {self.url}, 错误: {e}, 当前重试次数: {retry_count}")
|
514
|
+
finally:
|
515
|
+
self.response.close()
|
516
|
+
self.response = None
|
492
517
|
if retry_count < max_retries:
|
518
|
+
time.sleep(0.5 * retry_count)
|
493
519
|
retry_count += 1
|
494
|
-
time.sleep(0.5)
|
495
520
|
continue
|
496
|
-
|
497
|
-
|
498
|
-
self.response = None
|
521
|
+
else:
|
522
|
+
raise ValueError(f"超过当前最大重试次数,请求失败!当前重试次数: {retry_count}")
|
499
523
|
|
500
524
|
def detect_accept_ranges(self) -> bool:
|
501
525
|
detect_settings = self.request_settings.copy()
|
@@ -507,13 +531,7 @@ class Request:
|
|
507
531
|
raise ValueError("HTTP状态码错误")
|
508
532
|
|
509
533
|
self.content_length = int(head_response.headers.get('content-length', 0))
|
510
|
-
# accept_ranges = str(head_response.headers.get('accept-ranges')).lower()
|
511
|
-
supports_range = True
|
512
534
|
|
513
|
-
# 根据检测结果使用不同下载方式
|
514
|
-
# if accept_ranges == 'none' or not self.content_length:
|
515
|
-
# supports_range = False
|
516
|
-
# else:
|
517
535
|
test_range_settings = detect_settings.copy()
|
518
536
|
test_range_settings.setdefault("headers", {})['Range'] = "bytes=0-63"
|
519
537
|
test_response = requests.request(
|
@@ -524,19 +542,23 @@ class Request:
|
|
524
542
|
head_data = test_response.content
|
525
543
|
content_type = test_response.headers.get("Content-Type")
|
526
544
|
|
527
|
-
if test_response.status_code == 206:
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
545
|
+
if test_response.status_code == 206 and len(head_data) == 64:
|
546
|
+
supports_range = True
|
547
|
+
elif test_response.status_code == 200:
|
548
|
+
supports_range = False
|
549
|
+
self.response = test_response
|
550
|
+
head_data = head_data[:64]
|
551
|
+
logging.debug(f"Range请求方式不支持, 实际{len(head_data)}")
|
552
|
+
else:
|
553
|
+
supports_range = False
|
554
|
+
logging.error(f"Range请求失败: {test_response.status_code}")
|
533
555
|
|
556
|
+
if not self.detector_info:
|
557
|
+
self.response = test_response
|
534
558
|
detector = FileTypeDetector()
|
535
559
|
self.detector_info = detector.get_detailed_info(
|
536
560
|
url=self.url, content_type=content_type, data=head_data
|
537
561
|
)
|
538
|
-
else:
|
539
|
-
supports_range = False
|
540
562
|
|
541
563
|
test_response.close()
|
542
564
|
return supports_range
|
@@ -5,7 +5,7 @@ cobweb/base/__init__.py,sha256=NanSxJr0WsqjqCNOQAlxlkt-vQEsERHYBzacFC057oI,222
|
|
5
5
|
cobweb/base/common_queue.py,sha256=hYdaM70KrWjvACuLKaGhkI2VqFCnd87NVvWzmnfIg8Q,1423
|
6
6
|
cobweb/base/item.py,sha256=1bS4U_3vzI2jzSSeoEbLoLT_5CfgLPopWiEYtaahbvw,1674
|
7
7
|
cobweb/base/logger.py,sha256=Vsg1bD4LXW91VgY-ANsmaUu-mD88hU_WS83f7jX3qF8,2011
|
8
|
-
cobweb/base/request.py,sha256=
|
8
|
+
cobweb/base/request.py,sha256=TQgXiQvV3QGJTpUcoxpaEAg2aC_pTwCgNTc7DWSliG8,22111
|
9
9
|
cobweb/base/response.py,sha256=L3sX2PskV744uz3BJ8xMuAoAfGCeh20w8h0Cnd9vLo0,11377
|
10
10
|
cobweb/base/seed.py,sha256=ddaWCq_KaWwpmPl1CToJlfCxEEnoJ16kjo6azJs9uls,5000
|
11
11
|
cobweb/base/task_queue.py,sha256=2MqGpHGNmK5B-kqv7z420RWyihzB9zgDHJUiLsmtzOI,6402
|
@@ -34,8 +34,8 @@ cobweb/utils/decorators.py,sha256=ZwVQlz-lYHgXgKf9KRCp15EWPzTDdhoikYUNUCIqNeM,11
|
|
34
34
|
cobweb/utils/dotting.py,sha256=L-jGSApdnFIP4jUWH6p5qIme0aJ1vyDrxAx8wOJWvcs,1960
|
35
35
|
cobweb/utils/oss.py,sha256=wmToIIVNO8nCQVRmreVaZejk01aCWS35e1NV6cr0yGI,4192
|
36
36
|
cobweb/utils/tools.py,sha256=14TCedqt07m4z6bCnFAsITOFixeGr8V3aOKk--L7Cr0,879
|
37
|
-
cobweb_launcher-3.1.
|
38
|
-
cobweb_launcher-3.1.
|
39
|
-
cobweb_launcher-3.1.
|
40
|
-
cobweb_launcher-3.1.
|
41
|
-
cobweb_launcher-3.1.
|
37
|
+
cobweb_launcher-3.1.38.dist-info/LICENSE,sha256=z1rxSIGOyzcSb3orZxFPxzx-0C1vTocmswqBNxpKfEk,1063
|
38
|
+
cobweb_launcher-3.1.38.dist-info/METADATA,sha256=NKJtHSfd5l5tmKedjsFsweW-U5c0yx4Qtm3_u3VLTa8,6051
|
39
|
+
cobweb_launcher-3.1.38.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92
|
40
|
+
cobweb_launcher-3.1.38.dist-info/top_level.txt,sha256=4GETBGNsKqiCUezmT-mJn7tjhcDlu7nLIV5gGgHBW4I,7
|
41
|
+
cobweb_launcher-3.1.38.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|