Python еквівалент заданої команди wget


77

Я намагаюся створити функцію Python, яка робить те саме, що і ця команда wget:

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

-c - Продовжуйте з того місця, де зупинилися, якщо завантаження перервано.

--read-timeout=5- Якщо більше 5 секунд не надходять нові дані, відмовтеся та спробуйте ще раз. З огляду на -cце означає, що він спробує знову з того місця, де зупинився.

--tries=0 - Повторіть назавжди.

Ці три аргументи, використані в тандемі, призводять до завантаження, яке не може провалитися.

Я хочу продублювати ці функції у своєму сценарії Python, але не знаю, з чого почати ...


3
Ну ні, завантаження може не вдатися з багатьох причин, але так. Ви вивчали модуль запитів ?
Ігуананот,

@Iguananaut Слід зазначити, що завантаження можна перервати за допомогою комбінації клавіш Ctrl + c спеціально за допомогою інструмента командного рядка wget (я вважаю, що це стандартний спосіб призупинити їх у wget, використовуючи wgetb -c the_URLдля відновлення). Дивіться ubuntuforums.org/showthread.php?t=991864
Brōtsyorfuzthrāx

Відповіді:


36

urllib.request повинен працювати. Просто налаштуйте його за певний час (не виконано), перевірте, чи вже існує локальний файл, чи надсилає GET із заголовком RANGE, вказуючи, наскільки далеко ви завантажили локальний файл. Обов’язково використовуйте read () для додавання до локального файлу, доки не з’явиться помилка.

Це також потенційно є дублікатом завантаження резюме urllib2 Python не працює при повторному підключенні мережі


Коли я намагаюся urllib.request.urlopenабо urllib.request.Requestз рядком, що містить url як аргумент url, я отримуюValueError: unknown url type
Ecko

2
@XamuelDvorak Ви насправді вводите URL-адресу? URL - адреса потрібна тип, наприклад http://, ftp://.
Євгеній К

Я використовував 'stackoverflow.com', у якому в моєму браузері немає нічого подібного перед собою.
Еко

Це показує, що для інших веб-сайтів. Я спробую ваше рішення
Ecko

101

Існує також приємний модуль 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швидше за все.
Blairg23,

1
@AshishKarpe Якщо ви користуєтесь Ubuntu, спробуйте sudo apt-get install python3-wget.
Brōtsyorfuzthrāx

1
@Shule Це справді хороший момент, якого я навіть не помічав, поки ти його не підняв. Я взагалі не грав із параметром continue з цим wgetмодулем Python, але ось джерело, якщо ви хочете це перевірити: bitbucket.org/techtonik/python-wget
Blairg23,

1
wgetпоставляється з дуже мало варіантів і, схоже, не підтримується. requestsперевершує в усіх відношеннях.
імрек

1
@ Blairg23 Тим часом у пакеті python wget прямо сказано, що це не параметри, сумісні з оригінальною wgetутилітою. FYI, ви навіть не можете встановити заголовок User-Agent, правда?
імрек

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

18

Мені довелося зробити щось подібне у версії Linux, яка не мала правильних параметрів, скомпільованих у wget. Цей приклад призначений для завантаження інструменту аналізу пам'яті '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()

15

Рішення, яке я часто вважаю більш простим і надійним, - це просто виконати команду терміналу в python. У вашому випадку:

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

5
Коли я отримую голос проти, особливо за надання зовсім іншого підходу, мені подобається знати, чому. Потрібно пояснити?
Йохан Обадія,

1
Схоже, аргументи для os.system неналежним чином захищені. Один "занадто багато в кінці. Крім того, він не працює на вікнах, оскільки у нього немає wget. Для цього вам потрібно зайти сюди: foreverlybored.org/misc/wget завантажити його та додати до середовища (PATH). Хоча хороше рішення, голосування;)
Абель

Дякуємо за ваші відгуки :)
Йохан Обадія

Використовуйте subprocess. ЗАВЖДИ використовувати subprocess. Тривіально просто влаштувати машину, яка використовує os.systemподібне для віддаленого введення користувачем.
Antti Haapala

11

Для Windows та Python 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()

Це не робить жодного з речей, про які вимагав ОП (і декількох речей, про які вони не просили).
мельпомена

1
Приклад спроби показати функцію багатозавантаженості wget
Egalicia

Цього ніхто не просив. OP попросив еквівалент -c, --read-timeout=5і --tries=0(з одним URL).
melpomene

Я розумію, вибачте :(
Егалісія

1
Я дуже радий бачити це тут, а випадковість є наріжним каменем Інтернету. Я міг би додати , в той час як тут , однак, що під час мого дослідження я натрапив на це для многопоточности і бібліотека запитів: запити багатопотокового 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
FYI: Це не буде працювати в Windows, оскільки wgetкоманда там не реалізована.
Габріель Фейр

-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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.