给定wget命令的Python等效项


76

我正在尝试创建一个与此wget命令具有相同功能的Python函数:

wget -c --read-timeout=5 --tries=0 "$URL"

-c -如果下载中断,请从上次中断的地方继续。

--read-timeout=5-如果5秒钟内没有新数据输入,请放弃并重试。鉴于-c此,它将从上次中断的地方再次尝试。

--tries=0 -永远重试。

串联使用的这三个参数导致下载不会失败。

我想在我的Python脚本中复制这些功能,但是我不知道从哪里开始...


3
好吧,不,下载可能会由于多种原因而失败,是的。您是否研究了请求模块?
Iguananaut 2014年

@Iguananaut应该注意的是,无论如何都可以使用命令行wget工具用Ctrl + c中断下载(我相信这是在wget中暂停它们并使用wgetb -c the_URL恢复的标准方法)。见ubuntuforums.org/showthread.php?t=991864
Brōtsyorfuzthrāx

Answers:


34

urllib.request应该可以工作。只需在一段时间(未完成)循环中进行设置,检查本地文件是否已存在,是否发送带有RANGE标头的GET,并指定下载本地文件的距离。确保使用read()附加到本地文件,直到发生错误。

这也可能是Python urllib2的副本,当网络重新连接时,恢复下载不起作用


当我尝试urllib.request.urlopenurllib.request.Request使用包含url作为url参数的字符串时,我得到ValueError: unknown url type
Ecko 2015年

2
@XamuelDvorak您实际上是在输入URL吗?一个URL需要的类型,例如http://ftp://
尤金·K

我使用的是“ stackoverflow.com”,在我的浏览器中,它前面没有任何此类内容。
2015年

它显示了其他网站。我将尝试您的解决方案
Ecko 2015年

98

还有一个名为Python的漂亮模块wget,非常易于使用。在这里找到。

这证明了设计的简单性:

>>> 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文件有问题),请尝试此解决方案

编辑:您还可以使用该out参数来使用自定义输出目录,而不是当前工作目录。

>>> output_directory = <directory_name>
>>> filename = wget.download(url, out=output_directory)
>>> filename
'razorback.mp3'

3
抱歉,您的回复很晚,由于某些原因没有看到此通知。您pip install wget最有可能需要。
布莱格23年

1
@AshishKarpe如果您使用的是Ubuntu,请尝试sudo apt-get install python3-wget。
Brōtsyorfuzthrāx

1
@Shule这是一个非常好的观点,直到您提出来,我才意识到。我在此wgetPython模块中根本没有使用过参数参数,但是如果您想查看该参数,请
参见以下资源

1
wget带有很少的选项,并且似乎没有得到维护。requests在各方面都优越。
imrek '19

1
@ Blairg23同时,python wget软件包明确表示,它与原始wget实用程序不兼容。仅供参考,您甚至无法设置User-Agent标头,可以吗?
imrek '19

21
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这里没有等效项。只需下载文件三次。
Phani Rithvij '19

18

我必须在没有将正确的选项编译到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()

14

我经常发现更简单,更可靠的解决方案是,只需在python中执行终端命令。在您的情况下:

import os
url = 'https://www.someurl.com'
os.system(f"""wget -c --read-timeout=5 --tries=0 "{url}"""")

5
当我投下反对票时,尤其是在提供一种完全不同的方法时,我想知道为什么。关心解释?
Yohan Obadia

1
似乎os.system的args被错误地转义。最后一个”。另外,由于它没有wget,因此在Windows上不起作用。为此,您需要转到这里:eternallybored.org/misc/wget下载并将其添加到环境(PATH)中。好的解决方案,令人讨厌;)
Abel Dantas

感谢您的反馈意见:)
Yohan Obadia

使用subprocess始终使用subprocess。轻而易举地将使用os.system此类机器进行远程用户输入的机器打包。
Antti Haapala

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”不是必需的。默认情况下,该文件未重命名,并且下载文件夹是您的本地路径。


2

这是torchvision库采用的代码:

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`)

1

让我为线程提供一个示例,以防您要下载许多文件。

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要求的任何事情(以及他们没有要求的几件事)。
melpomene

1
该示例尝试显示wget的多下载功能
Egalicia '17

没有人要求。OP要求的等价-c--read-timeout=5--tries=0(同一个URL)。
melpomene

我了解,抱歉:(
Egalicia '17

1
我很高兴在这里看到它,机缘巧合是互联网的基石。我可能会在这里补充一点,在我的研究过程中,我遇到了有关多线程和请求库的问题:requests-threaded github.com/requests/requests-threads
米勒大猩猩

1

像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

2
仅供参考:由于在Windowswget中未实现该命令,因此在Windows上将无法使用。
加百利博览会

-1

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.