Estou tentando baixar e salvar uma imagem da web usando o requests
módulo python .
Aqui está o código (de trabalho) que eu usei:
img = urllib2.urlopen(settings.STATICMAP_URL.format(**data))
with open(path, 'w') as f:
f.write(img.read())
Aqui está o novo código (que não funciona) usando 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)
Você pode me ajudar em qual atributo da resposta usar requests
?
python
urllib2
python-requests
shkschneider
fonte
fonte
Respostas:
Você pode usar o
response.raw
objeto de arquivo ou iterar sobre a resposta.Usar o
response.raw
objeto semelhante a arquivo não decodifica, por padrão, as respostas compactadas (com GZIP ou desinflar). Você pode forçá-lo a descomprimir para você de qualquer maneira, definindo odecode_content
atributo comoTrue
(requests
define-oFalse
para controlar a decodificação). Você pode usar oshutil.copyfileobj()
Python para transmitir os dados para um objeto de arquivo:Para iterar sobre a resposta, use um loop; iterar dessa maneira garante que os dados sejam descompactados nesse estágio:
Isso lerá os dados em blocos de 128 bytes; se você achar que outro tamanho de pedaço funciona melhor, use o
Response.iter_content()
método com um tamanho de pedaço personalizado:Observe que você precisa abrir o arquivo de destino no modo binário para garantir que o python não tente e traduza novas linhas para você. Também configuramos
stream=True
para querequests
não faça o download da imagem inteira primeiro na memória.fonte
r2 = requests.post(r.url, data); print r2.content
. Mas agora eu também quero saberfilename
. é o seu caminho limpo? - atualmente encontrei o nome do arquivo no cabeçalho -r2.headers['content-disposition']
que me dá uma saída como:'attachment; filename=DELS36532G290115.csi'
Estou analisando essa cadeia de caracteres para o nome do arquivo ... é o caminho mais limpo?content-disposition
cabeçalho é o caminho a percorrer aqui; usecgi.parse_header()
para analisá-lo e obter os parâmetros;params = cgi.parse_header(r2.headers['content-disposition'])[1]
entãoparams['filename']
.requests.Response
próprio :for chunk in r: ...
. A chamadaiter_content()
sem achunk_size
irá iterar em pedaços de 1 byte .response.ok
nunca foi documentado e produz true para qualquer status 1xx, 2xx ou 3xx, mas apenas uma resposta 200 tem um corpo de resposta.Obtenha um objeto parecido com um arquivo da solicitação e copie-o para um arquivo. Isso também evitará a leitura de tudo na memória de uma só vez.
fonte
r.raw.decode_content = True
antesshutil.copyfileobj(response.raw, out_file)
porqueby default, decode compressed responses (with GZIP or deflate)
, para obter uma imagem de arquivo zero.Que tal isso, uma solução rápida.
fonte
f = open("/Users/apple/Desktop/sample.jpg", 'wb')
o que você quer dizer com esse caminho! eu quero imagem de download paraif response.ok:
Tenho a mesma necessidade de baixar imagens usando solicitações. Tentei pela primeira vez a resposta de Martijn Pieters e funciona bem. Mas quando fiz um perfil nessa função simples, descobri que ele usa tantas chamadas de função em comparação com urllib e urllib2.
Eu tentei da maneira recomendada pelo autor do módulo de pedidos:
Isso reduziu muito o número de chamadas de função, agilizando a minha aplicação. Aqui está o código do meu criador de perfil e o resultado.
O resultado para testRequest:
E o resultado para testRequest2:
fonte
chunk_size
parâmetro com o padrão 1, por issoiter_content
está iterando no fluxo de resultados 1 byte por vez. Veja a documentação python-requests.org/en/latest/api/… .PIL
aqui, bastawith open(image_name, 'wb') as outfile: outfile.write(r.content)
.PIL
também não está na biblioteca padrão, tornando isso um pouco menos portátil.iter_content
é lento porque vocêchunk_size
é muito pequeno; se você aumentar para 100k, será muito mais rápido.Isso pode ser mais fácil do que usar
requests
. Esta é a única vez que sugiro não usarrequests
para fazer coisas HTTP.Forro dois usando
urllib
:Há também um bom módulo Python chamado
wget
que é bastante fácil de usar. Encontrado aqui .Isso demonstra a simplicidade do design:
Aproveitar.
Editar: você também pode adicionar um
out
parâmetro para especificar um caminho.fonte
wget
sem aborrecimentos. Obrigado por declarar os benefícios do usourllib3
urllib.request.urlretrieve("http://example.com", "file.ext")
.O fragmento de código a seguir baixa um arquivo.
O arquivo é salvo com o nome do arquivo como no URL especificado.
fonte
Existem 2 maneiras principais:
Usando
.content
(mais simples / oficial) (consulte a resposta de Zhenyi Zhang ):Usando
.raw
(veja a resposta de Martijn Pieters ):O tempo de ambos mostra nenhuma diferença perceptível.
fonte
1.
resposta (usandoio.BytesIO
eImage
) foi a primeira que funcionou para mim no Python 3.6. Não esqueçafrom PIL import Image
(epip install Pillow
).Tão fácil quanto importar imagens e solicitações
fonte
Aqui está uma resposta mais amigável que ainda usa streaming.
Apenas defina essas funções e chame
getImage()
. Ele usará o mesmo nome de arquivo que o URL e gravará no diretório atual por padrão, mas ambos podem ser alterados.As
request
entranhas degetImage()
são baseadas na resposta aqui e as entranhas degetImageFast()
são baseadas na resposta acima .fonte
Vou postar uma resposta, pois não tenho representante suficiente para fazer um comentário, mas com o wget publicado por Blairg23, você também pode fornecer um parâmetro de saída para o caminho.
fonte
Esta é a primeira resposta que surge nas pesquisas do Google sobre como baixar um arquivo binário com solicitações. Caso você precise baixar um arquivo arbitrário com solicitações, você pode usar:
fonte
.close()
. Esta é a melhor resposta a partir de 2019, eu acho.Foi assim que eu fiz
fonte
Você pode fazer algo assim:
fonte