Jeśli mam adres URL, który po przesłaniu w przeglądarce internetowej wyskakuje okno dialogowe do zapisania pliku zip, jak powinienem przechwycić i pobrać ten plik zip w Pythonie?
Jeśli mam adres URL, który po przesłaniu w przeglądarce internetowej wyskakuje okno dialogowe do zapisania pliku zip, jak powinienem przechwycić i pobrać ten plik zip w Pythonie?
Odpowiedzi:
Większość ludzi zaleca używanie, requests
jeśli jest dostępne, a requests
dokumentacja zaleca to do pobierania i zapisywania surowych danych z adresu URL:
import requests
def download_url(url, save_path, chunk_size=128):
r = requests.get(url, stream=True)
with open(save_path, 'wb') as fd:
for chunk in r.iter_content(chunk_size=chunk_size):
fd.write(chunk)
Ponieważ odpowiedź zawiera pytanie o pobranie i zapisanie pliku zip, nie wdałem się w szczegóły dotyczące odczytu pliku zip. Zobacz jedną z wielu odpowiedzi poniżej, aby poznać możliwości.
Jeśli z jakiegoś powodu nie masz dostępu requests
, możesz użyć urllib.request
zamiast tego. Może nie być tak solidne, jak powyższe.
import urllib.request
def download_url(url, save_path):
with urllib.request.urlopen(url) as dl_file:
with open(save_path, 'wb') as out_file:
out_file.write(dl_file.read())
Wreszcie, jeśli nadal używasz Pythona 2, możesz użyć urllib2.urlopen
.
from contextlib import closing
def download_url(url, save_path):
with closing(urllib2.urlopen(url)) as dl_file:
with open(save_path, 'wb') as out_file:
out_file.write(dl_file.read())
O ile wiem, właściwym sposobem na to jest:
import requests, zipfile, StringIO
r = requests.get(zip_file_url, stream=True)
z = zipfile.ZipFile(StringIO.StringIO(r.content))
z.extractall()
oczywiście chciałbyś sprawdzić, czy GET się powiódł r.ok
.
W przypadku Pythona 3+, podrzędny moduł StringIO z modułem io i użyj BytesIO zamiast StringIO: Oto uwagi do wydania, które wspominają o tej zmianie.
import requests, zipfile, io
r = requests.get(zip_file_url)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall("/path/to/destination_directory")
z.extractall()
zz.extractall("/path/to/destination_directory")
urllib.request.urlretrieve(url, filename)
.
pd.read_table(z.open('filename'))
powyższego. Przydatne, jeśli masz link zip url zawierający wiele plików i chcesz tylko załadować jeden.
Z pomocą tego posta na blogu udało mi się to po prostu requests
. Rzecz w tym, że dziwne stream
jest to, że nie musimy wywoływać content
dużych żądań, które wymagałyby przetworzenia wszystkich na raz, zatykając pamięć. stream
Unika tego przez iteracja Dane jednym kawałku na raz.
url = 'https://www2.census.gov/geo/tiger/GENZ2017/shp/cb_2017_02_tract_500k.zip'
target_path = 'alaska.zip'
response = requests.get(url, stream=True)
handle = open(target_path, "wb")
for chunk in response.iter_content(chunk_size=512):
if chunk: # filter out keep-alive new chunks
handle.write(chunk)
handle.close()
Oto, co mam do pracy w Pythonie 3:
import zipfile, urllib.request, shutil
url = 'http://www....myzipfile.zip'
file_name = 'myzip.zip'
with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
shutil.copyfileobj(response, out_file)
with zipfile.ZipFile(file_name) as zf:
zf.extractall()
urllib.error.HTTPError: HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop.
:?
Użyj urllib2.urlopen lub możesz spróbować użyć doskonałego Requests
modułu i uniknąć bólów głowy urllib2:
import requests
results = requests.get('url')
#pass results.content onto secondary processing...
zipfile
modułu: zip = zipfile.ZipFile(results.content)
. Następnie wystarczy analizować poprzez pliki użyciu ZipFile.namelist()
, ZipFile.open()
alboZipFile.extractall()
Przyszedłem tutaj, szukając, jak zapisać plik .bzip2. Wkleję kod dla innych, którzy mogą tego szukać.
url = "http://api.mywebsite.com"
filename = "swateek.tar.gz"
response = requests.get(url, headers=headers, auth=('myusername', 'mypassword'), timeout=50)
if response.status_code == 200:
with open(filename, 'wb') as f:
f.write(response.content)
Chciałem tylko zapisać plik tak, jak jest.
Dzięki @yoavram za powyższe rozwiązanie, moja ścieżka URL jest połączona ze spakowanym folderem i napotykam błąd BADZipfile (plik nie jest plikiem zip) i było dziwne, gdy próbowałem kilka razy, aby pobrać adres URL i rozpakować wszystko nagle więc poprawiam nieco rozwiązanie. używając metody is_zipfile , jak tutaj
r = requests.get(url, stream =True)
check = zipfile.is_zipfile(io.BytesIO(r.content))
while not check:
r = requests.get(url, stream =True)
check = zipfile.is_zipfile(io.BytesIO(r.content))
else:
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall()