我有一个python脚本,可启动一个可下载文件的URL。有什么方法可以让python使用命令行显示与启动浏览器相反的下载进度?
Answers:
已更新您的示例网址:
我刚刚为此编写了一种超级简单的方法(将其略微修改),以将pdf刮出某个站点。注意,它仅在基于UNIX的系统(Linux,Mac OS)上正常运行,因为Powershell无法处理“ \ r”
import requests
link = "http://indy/abcde1245"
file_name = "download.data"
with open(file_name, "wb") as f:
print "Downloading %s" % file_name
response = requests.get(link, stream=True)
total_length = response.headers.get('content-length')
if total_length is None: # no content length header
f.write(response.content)
else:
dl = 0
total_length = int(total_length)
for data in response.iter_content(chunk_size=4096):
dl += len(data)
f.write(data)
done = int(50 * dl / total_length)
sys.stdout.write("\r[%s%s]" % ('=' * done, ' ' * (50-done)) )
sys.stdout.flush()
它使用了请求库,因此您需要安装它。这会将类似以下内容的内容输出到您的控制台中:
>下载download.data
> [=============]
脚本中进度条的宽度为52个字符(2[]个字符就是进度的50个字符)。每个=代表下载量的2%。
for data in response.iter_content():为for data in response.iter_content(chunk_size=total_length/100):。
您可以使用“ clint ”包(由“ requests”由同一作者编写)将一个简单的进度条添加到您的下载中,如下所示:
from clint.textui import progress
r = requests.get(url, stream=True)
path = '/some/path/for/file.txt'
with open(path, 'wb') as f:
total_length = int(r.headers.get('content-length'))
for chunk in progress.bar(r.iter_content(chunk_size=1024), expected_size=(total_length/1024) + 1):
if chunk:
f.write(chunk)
f.flush()
这将为您提供动态输出,如下所示:
[################################] 5210/5210 - 00:00:01
它也应该在多个平台上工作!您也可以使用.dots和.mill而不是.bar将条形更改为点或微调器。
请享用!
带有TQDM的Python 3
这是TQDM文档中建议的技术。
import urllib.request
from tqdm import tqdm
class DownloadProgressBar(tqdm):
def update_to(self, b=1, bsize=1, tsize=None):
if tsize is not None:
self.total = tsize
self.update(b * bsize - self.n)
def download_url(url, output_path):
with DownloadProgressBar(unit='B', unit_scale=True,
miniters=1, desc=url.split('/')[-1]) as t:
urllib.request.urlretrieve(url, filename=output_path, reporthook=t.update_to)
我认为您也可以使用click,它也有一个不错的进度栏库。
import click
with click.progressbar(length=total_size, label='Downloading files') as bar:
for file in files:
download(file)
bar.update(file.size)
请享用 !
ModuleNotFoundError: No module named 'click'上3.6.1。
很抱歉迟到了答案;刚刚更新了tqdm文档:
https://github.com/tqdm/tqdm/#hooks-and-callbacks
使用urllib.urlretrieve和面向对象:
import urllib
from tqdm.auto import tqdm
class TqdmUpTo(tqdm):
"""Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
def update_to(self, b=1, bsize=1, tsize=None):
"""
b : Blocks transferred so far
bsize : Size of each block
tsize : Total size
"""
if tsize is not None:
self.total = tsize
self.update(b * bsize - self.n) # will also set self.n = b * bsize
eg_link = "https://github.com/tqdm/tqdm/releases/download/v4.46.0/tqdm-4.46.0-py2.py3-none-any.whl"
eg_file = eg_link.split('/')[-1]
with TqdmUpTo(unit='B', unit_scale=True, unit_divisor=1024, miniters=1,
desc=eg_file) as t: # all optional kwargs
urllib.urlretrieve(
eg_link, filename=eg_file, reporthook=t.update_to, data=None)
t.total = t.n
或使用requests.get和文件包装器:
import requests
from tqdm.auto import tqdm
eg_link = "https://github.com/tqdm/tqdm/releases/download/v4.46.0/tqdm-4.46.0-py2.py3-none-any.whl"
eg_file = eg_link.split('/')[-1]
response = requests.get(eg_link, stream=True)
with tqdm.wrapattr(open(eg_file, "wb"), "write", miniters=1,
total=int(response.headers.get('content-length', 0)),
desc=eg_file) as fout:
for chunk in response.iter_content(chunk_size=4096):
fout.write(chunk)
您当然可以混合搭配技术。
import requests
from tqdm import tqdm
def download(url: str, fname: str):
resp = requests.get(url, stream=True)
total = int(resp.headers.get('content-length', 0))
with open(fname, 'wb') as file, tqdm(
desc=fname,
total=total,
unit='iB',
unit_scale=True,
unit_divisor=1024,
) as bar:
for data in resp.iter_content(chunk_size=1024):
size = file.write(data)
bar.update(size)
要点:https : //gist.github.com/yanqd0/c13ed29e29432e3cf3e7c38467f42f51
该tqdm软件包现在包含一个旨在处理这种情况的函数:wrapattr。您只需包装对象的read(或write)属性,然后tqdm即可处理其余部分。这是一个简单的下载功能,可将其与一起使用requests:
def download(url, filename):
import functools
import pathlib
import shutil
import requests
import tqdm
r = requests.get(url, stream=True, allow_redirects=True)
if r.status_code != 200:
r.raise_for_status() # Will only raise for 4xx codes, so...
raise RuntimeError(f"Request to {url} returned status code {r.status_code}")
file_size = int(r.headers.get('Content-Length', 0))
path = pathlib.Path(filename).expanduser().resolve()
path.parent.mkdir(parents=True, exist_ok=True)
desc = "(Unknown total file size)" if file_size == 0 else ""
r.raw.read = functools.partial(r.raw.read, decode_content=True) # Decompress if needed
with tqdm.tqdm.wrapattr(r.raw, "read", total=file_size, desc=desc) as r_raw:
with path.open("wb") as f:
shutil.copyfileobj(r_raw, f)
return path
#ToBeOptimized-基准 如果您想困惑自己的大脑并手工制作逻辑
#定义进度条功能
def print_progressbar(total,current,barsize=60):
progress=int(current*barsize/total)
completed= str(int(current*100/total)) + '%'
print('[' , chr(9608)*progress,' ',completed,'.'*(barsize-progress),'] ',str(i)+'/'+str(total), sep='', end='\r',flush=True)
#示例代码
total= 6000
barsize=60
print_frequency=max(min(total//barsize,100),1)
print("Start Task..",flush=True)
for i in range(1,total+1):
if i%print_frequency == 0 or i == 1:
print_progressbar(total,i,barsize)
print("\nFinished",flush=True)
#进度栏快照:
以下几行仅用于说明。在命令提示符下,您将看到单个进度条,其中显示了增量进度。
[ 0%............................................................] 1/6000
[██████████ 16%..................................................] 1000/6000
[████████████████████ 33%........................................] 2000/6000
[██████████████████████████████ 50%..............................] 3000/6000
[████████████████████████████████████████ 66%....................] 4000/6000
[██████████████████████████████████████████████████ 83%..........] 5000/6000
[████████████████████████████████████████████████████████████ 100%] 6000/6000
祝你好运,享受!
i才能正常工作。如果将这些i变量替换 为 current函数中的变量,则效果很好。