给定 wget 命令的 Python 等效项
Posted
技术标签:
【中文标题】给定 wget 命令的 Python 等效项【英文标题】:Python equivalent of a given wget command 【发布时间】:2014-08-12 08:50:55 【问题描述】:我正在尝试创建一个与此 wget 命令执行相同操作的 Python 函数:
wget -c --read-timeout=5 --tries=0 "$URL"
-c
- 如果下载中断,请从上次中断的地方继续。
--read-timeout=5
- 如果超过 5 秒没有新数据进入,请放弃并重试。给定-c
,这意味着它将从上次中断的地方重试。
--tries=0
- 永远重试。
这三个参数一起使用会导致下载不会失败。
我想在我的 Python 脚本中复制这些功能,但我不知道从哪里开始...
【问题讨论】:
嗯,不,下载可能失败的原因有很多,但是是的。你看过requests 模块吗? @Iguananaut 应该注意的是,无论如何,使用命令行 wget 工具可以故意使用 Ctrl+c 中断下载(我相信这是在 wget 中暂停它们的标准方法,使用wgetb -c the_URL
继续)。见ubuntuforums.org/showthread.php?t=991864
【参考方案1】:
urllib.request 应该可以工作。 只需在一段时间(未完成)循环中设置它,检查本地文件是否已经存在,如果它确实发送带有 RANGE 标头的 GET,指定您下载本地文件的距离。 请务必使用 read() 追加到本地文件,直到发生错误。
这也可能与 Python urllib2 resume download doesn't work when network reconnects 重复
【讨论】:
当我尝试urllib.request.urlopen
或urllib.request.Request
使用包含url 作为url 参数的字符串时,我得到ValueError: unknown url type
@XamuelDvorak 你真的在输入一个 URL 吗? url 需要类型,例如http://
, ftp://
.
我使用的是“***.com”,在我的浏览器中,它前面没有任何此类内容。
它显示了其他网站。我会试试你的解决方案【参考方案2】:
import urllib2
import time
max_attempts = 80
attempts = 0
sleeptime = 10 #in seconds, no reason to continuously try if network is down
#while true: #Possibly Dangerous
while attempts < max_attempts:
time.sleep(sleeptime)
try:
response = urllib2.urlopen("http://example.com", timeout = 5)
content = response.read()
f = open( "local/index.html", 'w' )
f.write( content )
f.close()
break
except urllib2.URLError as e:
attempts += 1
print type(e)
【讨论】:
这里没有-c
等价物。只需下载文件三次。【参考方案3】:
还有一个不错的 Python 模块,名为 wget
,非常易于使用。请记住,该软件包自 2015 年以来没有更新,也没有实现许多重要功能,因此使用其他方法可能会更好。这完全取决于您的用例。对于简单的下载,这个模块就是票。如果您需要做更多,还有其他解决方案。
>>> import wget
>>> url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'
>>> filename = wget.download(url)
100% [................................................] 3841532 / 3841532>
>> filename
'razorback.mp3'
享受吧。
但是,如果 wget
不起作用(我在处理某些 PDF 文件时遇到了问题),请尝试 this solution。
编辑:您还可以使用out
参数来使用自定义输出目录而不是当前工作目录。
>>> output_directory = <directory_name>
>>> filename = wget.download(url, out=output_directory)
>>> filename
'razorback.mp3'
【讨论】:
抱歉回复晚了,由于某种原因没有看到这个通知。您最有可能需要pip install wget
。
@AshishKarpe 如果您使用的是 Ubuntu,请尝试 sudo apt-get install python3-wget。
@Shule 这是一个非常好的观点,直到你提出来我才注意到。我没有使用过这个 wget
Python 模块的 continue 参数,但是如果你想查看它,这里是源代码:bitbucket.org/techtonik/python-wget
wget
提供的选项很少,似乎没有得到维护。 requests
各方面都出类拔萃。
@Blairg23 同时,python wget 包明确表示,它不是与原始wget
实用程序兼容的选项。仅供参考,您甚至不能设置 User-Agent 标头,可以吗?【参考方案4】:
我不得不在一个没有正确选项编译到 wget 的 linux 版本上做这样的事情。此示例用于下载内存分析工具“guppy”。我不确定它是否重要,但我保持目标文件的名称与 url 目标名称相同...
这是我想出的:
python -c "import requests; r = requests.get('https://pypi.python.org/packages/source/g/guppy/guppy-0.1.10.tar.gz') ; open('guppy-0.1.10.tar.gz' , 'wb').write(r.content)"
这是单行,这里的可读性更强:
import requests
fname = 'guppy-0.1.10.tar.gz'
url = 'https://pypi.python.org/packages/source/g/guppy/' + fname
r = requests.get(url)
open(fname , 'wb').write(r.content)
这适用于下载 tarball。下载后我能够解压并下载它。
编辑:
为了解决一个问题,这里有一个打印到 STDOUT 的进度条的实现。没有clint
包,可能有一种更便携的方法可以做到这一点,但这已经在我的机器上进行了测试并且工作正常:
#!/usr/bin/env python
from clint.textui import progress
import requests
fname = 'guppy-0.1.10.tar.gz'
url = 'https://pypi.python.org/packages/source/g/guppy/' + fname
r = requests.get(url, stream=True)
with open(fname, '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()
【讨论】:
【参考方案5】:让我改进一个带有线程的示例,以防你想下载很多文件。
import math
import random
import threading
import requests
from clint.textui import progress
# You must define a proxy list
# I suggests https://free-proxy-list.net/
proxies =
0: 'http': 'http://34.208.47.183:80',
1: 'http': 'http://40.69.191.149:3128',
2: 'http': 'http://104.154.205.214:1080',
3: 'http': 'http://52.11.190.64:3128'
# you must define the list for files do you want download
videos = [
"https://i.stack.imgur.com/g2BHi.jpg",
"https://i.stack.imgur.com/NURaP.jpg"
]
downloaderses = list()
def downloaders(video, selected_proxy):
print("Downloading file named by proxy ...".format(video, selected_proxy))
r = requests.get(video, stream=True, proxies=selected_proxy)
nombre_video = video.split("/")[3]
with open(nombre_video, '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()
for video in videos:
selected_proxy = proxies[math.floor(random.random() * len(proxies))]
t = threading.Thread(target=downloaders, args=(video, selected_proxy))
downloaderses.append(t)
for _downloaders in downloaderses:
_downloaders.start()
【讨论】:
这并没有完成 OP 要求的任何事情(以及他们没有要求的几件事)。 示例尝试展示 wget 多下载功能 没有人要求这样做。 OP 要求等效于-c
、--read-timeout=5
和 --tries=0
(使用单个 URL)。
我明白了,对不起:(
我很高兴在这里看到它,偶然发现是互联网的基石。不过,我可能会在这里补充一点,在我的研究过程中,我遇到了多线程和请求库:requests-threaded github.com/requests/requests-threads【参考方案6】:
像py一样简单:
class Downloder():
def download_manager(self, url, destination='Files/DownloderApp/', try_number="10", time_out="60"):
#threading.Thread(target=self._wget_dl, args=(url, destination, try_number, time_out, log_file)).start()
if self._wget_dl(url, destination, try_number, time_out, log_file) == 0:
return True
else:
return False
def _wget_dl(self,url, destination, try_number, time_out):
import subprocess
command=["wget", "-c", "-P", destination, "-t", try_number, "-T", time_out , url]
try:
download_state=subprocess.call(command)
except Exception as e:
print(e)
#if download_state==0 => successfull download
return download_state
【讨论】:
仅供参考:这在 Windows 上不起作用,因为wget
命令没有在那里实现。【参考方案7】:
我经常发现更简单、更强大的解决方案是在 python 中简单地执行终端命令。在你的情况下:
import os
url = 'https://www.someurl.com'
os.system(f"""wget -c --read-timeout=5 --tries=0 "url"""")
【讨论】:
当我投反对票时,尤其是在提供完全不同的方法时,我想知道为什么。需要解释一下吗? 看起来 os.system 的 args 转义不正确。最后一个 " 太多了。此外,它在 Windows 上不起作用,因为它没有 wget。为此,您需要去这里:eternallybored.org/misc/wget 下载它并将其添加到环境(PATH)中。不过,很好的解决方案,赞成;) 感谢您的反馈:) 使用subprocess
。 总是使用subprocess
。很容易掌握一台使用 os.system
这样的机器进行远程用户输入。【参考方案8】:
TensorFlow 让生活更轻松。 文件路径为我们提供了下载文件的位置。
import tensorflow as tf
tf.keras.utils.get_file(origin='https://storage.googleapis.com/tf-datasets/titanic/train.csv',
fname='train.csv',
untar=False, extract=False)
【讨论】:
谈论矫枉过正【参考方案9】:对于 Windows 和 Python 3.x,关于在下载时重命名文件,我贡献了两分钱:
-
安装wget 模块:
pip install wget
使用 wget :
import wget
wget.download('Url', 'C:\\PathToMyDownloadFolder\\NewFileName.extension')
真正有效的命令行示例:
python -c "import wget; wget.download(""https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.17.2.tar.xz"", ""C:\\Users\\TestName.TestExtension"")"
注意:'C:\\PathToMyDownloadFolder\\NewFileName.extension' 不是强制性的。默认不重命名文件,下载文件夹是你的本地路径。
【讨论】:
【参考方案10】:这是torchvision library采用的代码:
import urllib
def download_url(url, root, filename=None):
"""Download a file from a url and place it in root.
Args:
url (str): URL to download file from
root (str): Directory to place downloaded file in
filename (str, optional): Name to save the file under. If None, use the basename of the URL
"""
root = os.path.expanduser(root)
if not filename:
filename = os.path.basename(url)
fpath = os.path.join(root, filename)
os.makedirs(root, exist_ok=True)
try:
print('Downloading ' + url + ' to ' + fpath)
urllib.request.urlretrieve(url, fpath)
except (urllib.error.URLError, IOError) as e:
if url[:5] == 'https':
url = url.replace('https:', 'http:')
print('Failed download. Trying https -> http instead.'
' Downloading ' + url + ' to ' + fpath)
urllib.request.urlretrieve(url, fpath)
如果您可以依赖 torchvision 库,那么您也可以这样做:
from torchvision.datasets.utils import download_url
download_url('http://something.com/file.zip', '~/my_folder`)
【讨论】:
以上是关于给定 wget 命令的 Python 等效项的主要内容,如果未能解决你的问题,请参考以下文章
具有用户名和 api 令牌的 CURL 的 Python 等效项
case/switch 语句的 Python 等效项是啥? [复制]
Perl 的 require 命令的 java 等效项是啥? [关闭]