Próbuję pobrać i zapisać obraz z Internetu za pomocą requests
modułu Pythona .
Oto (działający) kod, którego użyłem:
img = urllib2.urlopen(settings.STATICMAP_URL.format(**data))
with open(path, 'w') as f:
f.write(img.read())
Oto nowy (niedziałający) kod wykorzystujący requests
:
r = requests.get(settings.STATICMAP_URL.format(**data))
if r.status_code == 200:
img = r.raw.read()
with open(path, 'w') as f:
f.write(img)
Czy możesz mi pomóc w zakresie tego, jaki atrybut odpowiedzi użyć requests
?
python
urllib2
python-requests
shkschneider
źródło
źródło
Odpowiedzi:
Możesz użyć
response.raw
obiektu pliku lub powtórzyć odpowiedź.Aby użyć
response.raw
obiektu podobnego do pliku, domyślnie nie dekoduje skompresowanych odpowiedzi (za pomocą GZIP lub deflate). W każdym razie możesz zmusić go do dekompresji, ustawiającdecode_content
atrybut naTrue
(requests
ustawia sięFalse
na kontrolę samego dekodowania). Następnie możesz użyćshutil.copyfileobj()
Pythona do strumieniowego przesyłania danych do obiektu pliku:Aby powtórzyć odpowiedź, użyj pętli; iteracja w ten sposób zapewnia dekompresję danych na tym etapie:
Spowoduje to odczyt danych w 128-bajtowych porcjach; jeśli uważasz, że inny rozmiar porcji działa lepiej, użyj
Response.iter_content()
metody z niestandardowym rozmiarem porcji:Zauważ, że musisz otworzyć plik docelowy w trybie binarnym, aby upewnić się, że Python nie spróbuje tłumaczyć nowych linii. Ustawiliśmy
stream=True
tak, abyrequests
najpierw nie pobierał całego obrazu do pamięci.źródło
r2 = requests.post(r.url, data); print r2.content
. Ale teraz też chcę wiedziećfilename
. czy jest ich jakiś oczyszczony sposób? - obecnie znalazłem nazwę pliku w nagłówku -r2.headers['content-disposition']
to daje mi wynik jako:'attachment; filename=DELS36532G290115.csi'
parsuję ten ciąg dla nazwy pliku ... czy jest ich bardziej przejrzysty sposób?content-disposition
nagłówek jest dobrym sposobem na przejście tutaj; użyj,cgi.parse_header()
aby go przeanalizować i uzyskać parametry;params = cgi.parse_header(r2.headers['content-disposition'])[1]
potemparams['filename']
.requests.Response
sama :for chunk in r: ...
. Wywołanieiter_content()
bez testerachunk_size
będzie powtarzane w 1 bajtowych porcjach .response.ok
nigdy nie zostało udokumentowane i daje wartość true dla dowolnego statusu 1xx, 2xx lub 3xx, ale tylko 200 odpowiedzi ma treść odpowiedzi.Pobierz z żądania obiekt podobny do pliku i skopiuj go do pliku. Pozwoli to również uniknąć wczytywania całej pamięci do pamięci naraz.
źródło
r.raw.decode_content = True
wcześniej,shutil.copyfileobj(response.raw, out_file)
ponieważby default, decode compressed responses (with GZIP or deflate)
, aby uzyskać obraz o zerowym pliku.A może to szybkie rozwiązanie.
źródło
f = open("/Users/apple/Desktop/sample.jpg", 'wb')
co masz na myśli mówiąc o tej ścieżce? Chcę pobrać obrazif response.ok:
Mam taką samą potrzebę pobierania zdjęć za pomocą żądań. Najpierw wypróbowałem odpowiedź Martijna Pietersa i działa ona dobrze. Ale kiedy stworzyłem profil dla tej prostej funkcji, odkryłem, że używa ona tak wielu wywołań funkcji w porównaniu do urllib i urllib2.
Następnie wypróbowałem sposób zalecany przez autora modułu żądań:
To znacznie bardziej zmniejszyło liczbę wywołań funkcji, a tym samym przyspieszyło moją aplikację. Oto kod mojego profilera i wynik.
Wynik testu testRequest:
Wynik testu testRequest2:
źródło
chunk_size
parametru, który domyślnie ma wartość 1, więciter_content
iteruje się w strumieniu wyników 1 bajt naraz. Zobacz dokumentację python-requests.org/en/latest/api/… .PIL
,with open(image_name, 'wb') as outfile: outfile.write(r.content)
wystarczy.PIL
nie ma go również w standardowej bibliotece, co czyni go nieco mniej przenośnym.iter_content
jest wolny, ponieważ twójchunk_size
jest za mały, jeśli zwiększysz go do 100k, będzie on znacznie szybszy.To może być łatwiejsze niż używanie
requests
. To jedyny raz, kiedy zasugeruję, aby nie używaćrequests
do robienia rzeczy HTTP.Dwie wkładki przy użyciu
urllib
:Jest też ładny moduł o nazwie Python,
wget
który jest dość łatwy w użyciu. Znaleziono tutaj .To pokazuje prostotę projektu:
Cieszyć się.
Edycja: Możesz także dodać
out
parametr, aby określić ścieżkę.źródło
wget
bez żadnych problemów. Dziękujemy za stwierdzenie korzyści płynących z używaniaurllib3
urllib.request.urlretrieve("http://example.com", "file.ext")
.Poniższy fragment kodu pobiera plik.
Plik jest zapisywany z nazwą pliku podaną w określonym adresie URL.
źródło
Istnieją 2 główne sposoby:
Za pomocą
.content
(najprostszy / oficjalny) (patrz odpowiedź Zhenyi Zhanga ):Używając
.raw
(patrz odpowiedź Martijna Pietersa ):Oba czasy nie wykazują zauważalnej różnicy.
źródło
1.
odpowiedź (używającio.BytesIO
iImage
) była pierwszą, która działała dla mnie w Pythonie 3.6. Nie zapomnijfrom PIL import Image
(ipip install Pillow
).Tak proste, jak importowanie obrazu i wniosków
źródło
Oto bardziej przyjazna dla użytkownika odpowiedź, która nadal korzysta z przesyłania strumieniowego.
Wystarczy zdefiniować te funkcje i wywołać
getImage()
. Będzie używał tej samej nazwy pliku co adres URL i zapisuje domyślnie w bieżącym katalogu, ale oba można zmienić.W
request
wnętrznościgetImage()
są oparte na odpowiedź tutaj i wnętrznościgetImageFast()
są oparte na odpowiedź powyżej .źródło
Zamierzam opublikować odpowiedź, ponieważ nie mam wystarczającej liczby przedstawicieli do skomentowania, ale dzięki wget opublikowanemu przez Blairg23 możesz również podać parametr out dla ścieżki.
źródło
Jest to pierwsza odpowiedź, która pojawia się w przypadku wyszukiwań Google dotyczących sposobu pobierania pliku binarnego z żądaniami. Jeśli chcesz pobrać dowolny plik z żądaniami, możesz użyć:
źródło
.close()
. To chyba najlepsza odpowiedź na 2019 rok.Tak to zrobiłem
źródło
Możesz zrobić coś takiego:
źródło