给定 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.urlopenurllib.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】:

对于 WindowsPython 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 等效项

diff 命令的 Windows 等效项是啥?

case/switch 语句的 Python 等效项是啥? [复制]

Perl 的 require 命令的 java 等效项是啥? [关闭]

C# 中是不是有 .isConnected 功能的 python 等效项

CMD 命令的 MS-DOS 等效项?