提交 5399f695 编写于 作者: H Hsury

优化超时重试逻辑

上级 1edee325
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<h1 align="center">- BiliDrive -</h1> <h1 align="center">- BiliDrive -</h1>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/version-2019.10.30-green.svg?longCache=true&style=for-the-badge"> <img src="https://img.shields.io/badge/version-2019.11.2-green.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/license-SATA-blue.svg?longCache=true&style=for-the-badge"> <img src="https://img.shields.io/badge/license-SATA-blue.svg?longCache=true&style=for-the-badge">
</p> </p>
......
...@@ -8,11 +8,13 @@ import math ...@@ -8,11 +8,13 @@ import math
import os import os
import re import re
import requests import requests
import shlex
import signal import signal
import struct import struct
import sys import sys
import threading import threading
import time import time
import traceback
import types import types
from bilibili import Bilibili from bilibili import Bilibili
...@@ -67,7 +69,7 @@ def image_upload(data, cookies): ...@@ -67,7 +69,7 @@ def image_upload(data, cookies):
headers = { headers = {
'Origin': "https://t.bilibili.com", 'Origin': "https://t.bilibili.com",
'Referer': "https://t.bilibili.com/", 'Referer': "https://t.bilibili.com/",
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36",
} }
files = { files = {
'file_up': (f"{int(time.time() * 1000)}.bmp", data), 'file_up': (f"{int(time.time() * 1000)}.bmp", data),
...@@ -75,17 +77,27 @@ def image_upload(data, cookies): ...@@ -75,17 +77,27 @@ def image_upload(data, cookies):
'category': "daily", 'category': "daily",
} }
try: try:
response = requests.post(url, headers=headers, cookies=cookies, files=files).json() response = requests.post(url, headers=headers, cookies=cookies, files=files, timeout=5).json()
except: except:
response = None response = None
return response return response
def image_download(url): def image_download(url):
headers = {
'Referer': "http://t.bilibili.com/",
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36",
}
content = []
last_chunk_time = None
try: try:
response = requests.get(url).content for chunk in requests.get(url, headers=headers, timeout=5, stream=True).iter_content(64 * 1024):
if last_chunk_time is not None and time.time() - last_chunk_time > 5:
return None
content.append(chunk)
last_chunk_time = time.time()
return b"".join(content)
except: except:
response = None return None
return response
def log(message): def log(message):
Bilibili._log(message) Bilibili._log(message)
...@@ -141,45 +153,58 @@ def login_handle(args): ...@@ -141,45 +153,58 @@ def login_handle(args):
def upload_handle(args): def upload_handle(args):
def core(index, block): def core(index, block):
block_sha1 = calc_sha1(block, hexdigest=True) try:
full_block = bmp_header(block) + block block_sha1 = calc_sha1(block, hexdigest=True)
full_block_sha1 = calc_sha1(full_block, hexdigest=True) full_block = bmp_header(block) + block
url = skippable(full_block_sha1) full_block_sha1 = calc_sha1(full_block, hexdigest=True)
if url: url = skippable(full_block_sha1)
# log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 已存在于服务器") if url:
block_dict[index] = { # log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 已存在于服务器")
'url': url, block_dict[index] = {
'size': len(block), 'url': url,
'sha1': block_sha1, 'size': len(block),
} 'sha1': block_sha1,
done_flag.release() }
else: done_flag.release()
# log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 开始上传")
for _ in range(10):
response = image_upload(full_block, cookies)
if response:
if response['code'] == 0:
url = response['data']['image_url']
log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 上传完毕")
block_dict[index] = {
'url': url,
'size': len(block),
'sha1': block_sha1,
}
done_flag.release()
break
elif response['code'] == -4:
terminate_flag.set()
log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 第{_ + 1}次上传失败, 请重新登录")
break
log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 第{_ + 1}次上传失败")
else: else:
terminate_flag.set() # log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 开始上传")
for _ in range(10):
response = image_upload(full_block, cookies)
if response:
if response['code'] == 0:
url = response['data']['image_url']
log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 上传完毕")
block_dict[index] = {
'url': url,
'size': len(block),
'sha1': block_sha1,
}
done_flag.release()
break
elif response['code'] == -4:
terminate_flag.set()
log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 第{_ + 1}次上传失败, 请重新登录")
break
log(f"分块{index} ({len(block) / 1024 / 1024:.2f} MB) 第{_ + 1}次上传失败")
else:
terminate_flag.set()
except:
terminate_flag.set()
traceback.print_exc()
def skippable(sha1): def skippable(sha1):
url = default_url(sha1) url = default_url(sha1)
response = requests.head(url) headers = {
return url if response.status_code == 200 else None 'Referer': "http://t.bilibili.com/",
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36",
}
for _ in range(3):
try:
response = requests.head(url, headers=headers, timeout=5)
return url if response.status_code == 200 else None
except:
pass
return None
def write_history(first_4mb_sha1, meta_dict, url): def write_history(first_4mb_sha1, meta_dict, url):
history = read_history() history = read_history()
...@@ -249,24 +274,29 @@ def upload_handle(args): ...@@ -249,24 +274,29 @@ def upload_handle(args):
def download_handle(args): def download_handle(args):
def core(index, block_dict): def core(index, block_dict):
# log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 开始下载") try:
for _ in range(10): # log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 开始下载")
block = image_download(block_dict['url'])[62:] for _ in range(10):
if block: block = image_download(block_dict['url'])
if calc_sha1(block, hexdigest=True) == block_dict['sha1']: if block:
file_lock.acquire() block = block[62:]
f.seek(block_offset(index)) if calc_sha1(block, hexdigest=True) == block_dict['sha1']:
f.write(block) file_lock.acquire()
file_lock.release() f.seek(block_offset(index))
log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 下载完毕") f.write(block)
done_flag.release() file_lock.release()
break log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 下载完毕")
done_flag.release()
break
else:
log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 校验未通过")
else: else:
log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 校验未通过") log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) {_ + 1}次下载失败")
else: else:
log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 第{_ + 1}次下载失败") terminate_flag.set()
else: except:
terminate_flag.set() terminate_flag.set()
traceback.print_exc()
def block_offset(index): def block_offset(index):
return sum(meta_dict['block'][i]['size'] for i in range(index)) return sum(meta_dict['block'][i]['size'] for i in range(index))
...@@ -301,10 +331,11 @@ def download_handle(args): ...@@ -301,10 +331,11 @@ def download_handle(args):
else: else:
# log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 需要重新下载") # log(f"分块{index} ({block_dict['size'] / 1024 / 1024:.2f} MB) 需要重新下载")
download_block_list.append(index) download_block_list.append(index)
log(f"{len(download_block_list)}个分块待下载")
else: else:
return None return None
else: else:
download_block_list = list(range(len(meta_dict['block']))) download_block_list = list(range(len(meta_dict['block'])))
done_flag = threading.Semaphore(0) done_flag = threading.Semaphore(0)
terminate_flag = threading.Event() terminate_flag = threading.Event()
file_lock = threading.Lock() file_lock = threading.Lock()
...@@ -334,7 +365,7 @@ def download_handle(args): ...@@ -334,7 +365,7 @@ def download_handle(args):
if __name__ == "__main__": if __name__ == "__main__":
signal.signal(signal.SIGINT, lambda signum, frame: os.kill(os.getpid(), 9)) signal.signal(signal.SIGINT, lambda signum, frame: os.kill(os.getpid(), 9))
parser = argparse.ArgumentParser(description="Bilibili Drive", epilog="By Hsury, 2019/10/30") parser = argparse.ArgumentParser(description="BiliDrive", epilog="By Hsury, 2019/11/2")
subparsers = parser.add_subparsers() subparsers = parser.add_subparsers()
history_parser = subparsers.add_parser("history", help="view upload history") history_parser = subparsers.add_parser("history", help="view upload history")
history_parser.set_defaults(func=history_handle) history_parser.set_defaults(func=history_handle)
...@@ -359,7 +390,7 @@ if __name__ == "__main__": ...@@ -359,7 +390,7 @@ if __name__ == "__main__":
shell = False shell = False
while True: while True:
if shell: if shell:
args = input("BiliDrive > ").split() args = shlex.split(input("BiliDrive > "))
if args == ["exit"]: if args == ["exit"]:
break break
elif args == ["help"]: elif args == ["help"]:
...@@ -377,4 +408,3 @@ if __name__ == "__main__": ...@@ -377,4 +408,3 @@ if __name__ == "__main__":
break break
except AttributeError: except AttributeError:
shell = True shell = True
parser.print_help()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册