Podstawowe pobieranie i zapisywanie plików http na dysk w Pythonie?

159

Jestem nowy w Pythonie i przeglądałem pytania i odpowiedzi w tej witrynie, aby znaleźć odpowiedź na moje pytanie. Jednak jestem początkującym i trudno mi zrozumieć niektóre rozwiązania. Potrzebuję bardzo podstawowego rozwiązania.

Czy ktoś mógłby mi wyjaśnić proste rozwiązanie „Pobieranie pliku przez http” i „Zapisywanie go na dysku w systemie Windows”?

Nie jestem też pewien, jak używać modułów shutil i os.

Plik, który chcę pobrać, ma mniej niż 500 MB i jest plikiem archiwum .gz.Jeśli ktoś może wyjaśnić, jak rozpakować archiwum i wykorzystać zawarte w nim pliki, byłoby świetnie!

Oto częściowe rozwiązanie, które napisałem z różnych połączonych odpowiedzi:

import requests
import os
import shutil

global dump

def download_file():
    global dump
    url = "http://randomsite.com/file.gz"
    file = requests.get(url, stream=True)
    dump = file.raw

def save_file():
    global dump
    location = os.path.abspath("D:\folder\file.gz")
    with open("file.gz", 'wb') as location:
        shutil.copyfileobj(dump, location)
    del dump

Czy ktoś mógłby wskazać błędy (poziom początkujący) i wyjaśnić łatwiejsze metody, aby to zrobić?

Dzięki!

arvindch
źródło

Odpowiedzi:

207

Czysty sposób na pobranie pliku to:

import urllib

testfile = urllib.URLopener()
testfile.retrieve("http://randomsite.com/file.gz", "file.gz")

Spowoduje to pobranie pliku ze strony internetowej i nadanie mu nazwy file.gz. To jedno z moich ulubionych rozwiązań, od pobierania obrazu przez urllib i python .

W tym przykładzie użyto urllibbiblioteki i bezpośrednio pobierze plik ze źródła.

Niebieski lód
źródło
3
Ok dzięki! Ale czy istnieje sposób, aby to działało poprzez żądania?
arvindch
5
Czy istnieje możliwość zapisania w /myfolder/file.gz?
John Snow,
17
Może nie ma lepszej możliwości niż wypróbowanie tego samemu? :) Z powodzeniem mogłem to zrobić testfile.retrieve("http://example.com/example.rpm", "/tmp/test.rpm").
Dharmit
18
Jest to przestarzałe od czasu Pythona 3.3, a rozwiązanie urllib.request.urlretrieve (patrz odpowiedź poniżej) jest „nowoczesnym” sposobem
MichielB
1
Jaki jest najlepszy sposób dodania nazwy użytkownika i hasła do tego kodu? tks
Estefy
110

Jak wspomniano tutaj :

import urllib
urllib.urlretrieve ("http://randomsite.com/file.gz", "file.gz")

EDIT:Jeśli nadal chcesz korzystać z żądań, spójrz na to lub to pytanie .

dparpyani
źródło
1
urllib zadziała, jednak wiele osób wydaje się zalecać używanie żądań zamiast urllib. Dlaczego tak jest?
arvindch
2
requestsjest niezwykle pomocny w porównaniu do urllibpracy z interfejsem API REST. Chyba że chcesz zrobić o wiele więcej, to powinno być dobre.
dparpyani
OK, teraz przeczytałem linki, które podałeś dla żądań użycia. Nie wiem, jak zadeklarować ścieżkę pliku do zapisania pobierania. Jak w tym celu używać systemów operacyjnych OS i shutil?
arvindch
62
Python3:import urllib.request urllib.request.urlretrieve(url, filename)
Flash
1
Nie jestem w stanie wyodrębnić kodu statusu http za pomocą tego, jeśli pobieranie się nie powiedzie
Aashish Thite
34

Używam wget .

Prosta i dobra biblioteka, jeśli chcesz dać przykład?

import wget

file_url = 'http://johndoe.com/download.zip'

file_name = wget.download(file_url)

Moduł wget obsługuje wersje Pythona 2 i Pythona 3

Ali
źródło
33

Cztery metody wykorzystujące wget, urllib i request.

#!/usr/bin/python
import requests
from StringIO import StringIO
from PIL import Image
import profile as profile
import urllib
import wget


url = 'https://tinypng.com/images/social/website.jpg'

def testRequest():
    image_name = 'test1.jpg'
    r = requests.get(url, stream=True)
    with open(image_name, 'wb') as f:
        for chunk in r.iter_content():
            f.write(chunk)

def testRequest2():
    image_name = 'test2.jpg'
    r = requests.get(url)
    i = Image.open(StringIO(r.content))
    i.save(image_name)

def testUrllib():
    image_name = 'test3.jpg'
    testfile = urllib.URLopener()
    testfile.retrieve(url, image_name)

def testwget():
    image_name = 'test4.jpg'
    wget.download(url, image_name)

if __name__ == '__main__':
    profile.run('testRequest()')
    profile.run('testRequest2()')
    profile.run('testUrllib()')
    profile.run('testwget()')

testRequest - 4469882 wywołania funkcji (4469842 prymitywne wywołania) w 20,236 sekund

testRequest2 - 8580 wywołań funkcji (wywołania pierwotne 8574) w 0,072 sekundy

testUrllib - 3810 wywołań funkcji (3775 wywołań pierwotnych) w 0,036 sekundy

testwget - 3489 wywołań funkcji w 0,020 sekundy

Saurabh yadav
źródło
1
Skąd masz liczbę wywołań funkcji?
Abdelhak
29

Dla Python3 + URLopener jest przestarzała. A kiedy zostanie użyty, otrzymasz błąd jak poniżej:

url_opener = urllib.URLopener () AttributeError: moduł „urllib” nie ma atrybutu „URLopener”

Więc spróbuj:

import urllib.request 
urllib.request.urlretrieve(url, filename)
Om Sao
źródło
1
Dziwne ... Dlaczego nikt nie głosuje na tę odpowiedź, kiedy Python 2 stał się przestarzały i tylko to rozwiązanie powinno działać poprawnie ...
wowkin2
1
Zgoda! Szarpałam włosy nad wcześniejszymi rozwiązaniami. Chciałbym móc zagłosować za 200 razy!
Yechiel K
5

Egzotyczne rozwiązanie dla systemu Windows

import subprocess

subprocess.run("powershell Invoke-WebRequest {} -OutFile {}".format(your_url, filename), shell=True)
Maks
źródło
1

Zacząłem tą ścieżką, ponieważ wget ESXi nie jest skompilowany z SSL i chciałem pobrać OVA ze strony internetowej dostawcy bezpośrednio na host ESXi, który znajduje się po drugiej stronie świata.

Musiałem wyłączyć zaporę (leniwy) / włączyć HTTPS poprzez edycję reguł (poprawne)

stworzył skrypt Pythona:

import ssl
import shutil
import tempfile
import urllib.request
context = ssl._create_unverified_context()

dlurl='https://somesite/path/whatever'
with urllib.request.urlopen(durl, context=context) as response:
    with open("file.ova", 'wb') as tmp_file:
        shutil.copyfileobj(response, tmp_file)

Biblioteki ESXi są trochę sparowane, ale instalator łasicy typu open source wydawał się używać urllib dla https ... więc zainspirowało mnie to do pójścia tą ścieżką

Jayme Snyder
źródło
-5

Innym czystym sposobem zapisania pliku jest:

import csv
import urllib

urllib.retrieve("your url goes here" , "output.csv")
Ala
źródło
Prawdopodobnie powinno to być urllib.urlretrievelub urllib.URLopener().retrieve, niejasne, o co ci chodzi.
mateor
9
Dlaczego importujesz plik csv, jeśli nadajesz tylko nazwę plikowi?
Azeezah M