【问题标题】:Python equivalent of a given wget command给定 wget 命令的 Python 等效项
【发布时间】: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

标签: python wget


【解决方案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://.
  • 我使用的是“stackoverflow.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,关于在下载时重命名文件,我贡献了两分钱:

    1. 安装wget 模块:pip install wget
    2. 使用 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`)
      

      【讨论】:

        猜你喜欢
        • 2016-01-26
        • 1970-01-01
        • 1970-01-01
        • 2013-09-12
        • 2013-02-02
        • 2013-08-30
        • 2010-12-21
        • 1970-01-01
        • 2011-12-24
        相关资源
        最近更新 更多