Python 如何使用请求下载图像
我正在尝试使用python的Python 如何使用请求下载图像,python,urllib2,python-requests,Python,Urllib2,Python Requests,我正在尝试使用python的请求模块从web下载并保存图像 以下是我使用的(工作)代码: img = urllib2.urlopen(settings.STATICMAP_URL.format(**data)) with open(path, 'w') as f: f.write(img.read()) 以下是使用请求的新(非工作)代码: r = requests.get(settings.STATICMAP_URL.format(**data)) if r.status_code =
请求
模块从web下载并保存图像
以下是我使用的(工作)代码:
img = urllib2.urlopen(settings.STATICMAP_URL.format(**data))
with open(path, 'w') as f:
f.write(img.read())
以下是使用请求的新(非工作)代码:
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)
您可以帮助我从请求中使用响应中的哪些属性吗?您可以使用,也可以迭代响应
使用response.raw
类文件对象默认情况下不会对压缩响应进行解码(使用GZIP或deflate)。通过将decode\u content
属性设置为True
(requests
将其设置为False
以控制解码本身),您可以强制它为您解压。然后,您可以使用Python将数据流传输到文件对象:
import requests
import shutil
r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
with open(path, 'wb') as f:
r.raw.decode_content = True
shutil.copyfileobj(r.raw, f)
要迭代响应,请使用循环;这样迭代可确保在此阶段解压缩数据:
r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
with open(path, 'wb') as f:
for chunk in r:
f.write(chunk)
这将以128字节块读取数据;如果您觉得另一个块大小更有效,请使用具有自定义块大小的:
r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
with open(path, 'wb') as f:
for chunk in r.iter_content(1024):
f.write(chunk)
注意,您需要以二进制模式打开目标文件,以确保python不会尝试为您翻译换行符。我们还设置了stream=True
,以便请求
不会首先将整个图像下载到内存中。从请求中获取类似文件的对象,并将其复制到文件中。这样也可以避免一次将整件事情读入内存
import shutil
import requests
url = 'http://example.com/img.png'
response = requests.get(url, stream=True)
with open('img.png', 'wb') as out_file:
shutil.copyfileobj(response.raw, out_file)
del response
我同样需要使用请求下载图像。我首先尝试了Martijn Pieters的答案,效果很好。但是,当我对这个简单函数进行概要分析时,我发现与urllib和urllib2相比,它使用了太多的函数调用
然后,我尝试了“请求”模块的作者编写的:
import requests
from PIL import Image
# python2.x, use this instead
# from StringIO import StringIO
# for python3.x,
from io import StringIO
r = requests.get('https://example.com/image.jpg')
i = Image.open(StringIO(r.content))
这大大减少了函数调用的数量,从而加快了我的应用程序。
这是我的分析器的代码和结果
#!/usr/bin/python
import requests
from StringIO import StringIO
from PIL import Image
import profile
def testRequest():
image_name = 'test1.jpg'
url = 'http://example.com/image.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'
url = 'http://example.com/image.jpg'
r = requests.get(url)
i = Image.open(StringIO(r.content))
i.save(image_name)
if __name__ == '__main__':
profile.run('testUrllib()')
profile.run('testUrllib2()')
profile.run('testRequest()')
testRequest的结果是:
343080 function calls (343068 primitive calls) in 2.580 seconds
以及testRequest2的结果:
3129 function calls (3105 primitive calls) in 0.024 seconds
这个怎么样,一个快速的解决方案
import requests
url = "http://craphound.com/images/1006884_2adf8fc7.jpg"
response = requests.get(url)
if response.status_code == 200:
with open("/Users/apple/Desktop/sample.jpg", 'wb') as f:
f.write(response.content)
这里有一个更加用户友好的答案,仍然使用流媒体
只需定义这些函数并调用getImage()
。默认情况下,它将使用与url相同的文件名并写入当前目录,但两者都可以更改
import requests
from StringIO import StringIO
from PIL import Image
def createFilename(url, name, folder):
dotSplit = url.split('.')
if name == None:
# use the same as the url
slashSplit = dotSplit[-2].split('/')
name = slashSplit[-1]
ext = dotSplit[-1]
file = '{}{}.{}'.format(folder, name, ext)
return file
def getImage(url, name=None, folder='./'):
file = createFilename(url, name, folder)
with open(file, 'wb') as f:
r = requests.get(url, stream=True)
for block in r.iter_content(1024):
if not block:
break
f.write(block)
def getImageFast(url, name=None, folder='./'):
file = createFilename(url, name, folder)
r = requests.get(url)
i = Image.open(StringIO(r.content))
i.save(file)
if __name__ == '__main__':
# Uses Less Memory
getImage('http://www.example.com/image.jpg')
# Faster
getImageFast('http://www.example.com/image.jpg')
请求getImage()
的胆量基于答案,而getImageFast()
的胆量基于答案。这可能比使用请求更容易。这是我唯一一次建议不要使用请求
来处理HTTP内容
使用urllib
的两行程序:
>>> import urllib
>>> urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
还有一个很好的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'
享受
编辑:您还可以添加一个out
参数来指定路径
>>> out_filepath = <output_filepath>
>>> filename = wget.download(url, out=out_filepath)
>>输出文件路径=
>>>filename=wget.download(url,out=out\u文件路径)
我将发布一个答案,因为我没有足够的代表发表评论,但是使用Blairg23发布的wget,您还可以为路径提供out参数
wget.download(url, out=path)
主要有两种方式:
使用.content
(最简单/官方)(请参阅):
使用.raw
(请参阅):
计时两者没有明显的区别。下面的代码片段下载一个文件
文件以指定的url保存,文件名为
import requests
url = "http://example.com/image.jpg"
filename = url.split("/")[-1]
r = requests.get(url, timeout=0.5)
if r.status_code == 200:
with open(filename, 'wb') as f:
f.write(r.content)
与导入图像和请求一样简单
from PIL import Image
import requests
img = Image.open(requests.get(url, stream = True).raw)
img.save('img1.jpg')
您可以这样做:
import requests
import random
url = "https://images.pexels.com/photos/1308881/pexels-photo-1308881.jpeg? auto=compress&cs=tinysrgb&dpr=1&w=500"
name=random.randrange(1,1000)
filename=str(name)+".jpg"
response = requests.get(url)
if response.status_code.ok:
with open(filename,'w') as f:
f.write(response.content)
这是谷歌搜索关于如何下载带有请求的二进制文件的第一个响应。如果您需要下载带有请求的任意文件,您可以使用:
import requests
url = 'https://s3.amazonaws.com/lab-data-collections/GoogleNews-vectors-negative300.bin.gz'
open('GoogleNews-vectors-negative300.bin.gz', 'wb').write(requests.get(url, allow_redirects=True).content)
我就是这样做的
import requests
from PIL import Image
from io import BytesIO
url = 'your_url'
files = {'file': ("C:/Users/shadow/Downloads/black.jpeg", open('C:/Users/shadow/Downloads/black.jpeg', 'rb'),'image/jpg')}
response = requests.post(url, files=files)
img = Image.open(BytesIO(response.content))
img.show()
我的方法是使用response.content(blob)并以二进制模式保存到文件中
img_blob = requests.get(url, timeout=5).content
with open(destination + '/' + title, 'wb') as img_file:
img_file.write(img_blob)
查看我的基于关键字从unsplash.com下载图像的网站。要使用r.raw,您需要设置stream=true这是否回答了您的问题?非常感谢您回来回答这个问题。尽管另一个答案是可行的,但这一个是跨越式的simplerIt值得注意的是,很少有服务器将其图像设置为GZIP,因为图像已经有了自己的压缩。这会适得其反,浪费CPU周期而没有什么好处。因此,虽然这可能是文本内容的问题,特别是图像的问题,但事实并非如此。我们有没有办法访问原始内容filename@phette23另外值得注意的是,Google PageSpeed在默认情况下会报告并执行此操作。应在shutil.copyfileobj(response.raw,out\u文件)之前设置r.raw.decode\u content=True
因为默认情况下,解码压缩响应(使用GZIP或deflate)
,所以您将获得零文件图像。这是因为您没有指定默认为1的chunk\u size
参数,所以iter\u content
在结果流上一次迭代1个字节。请参阅文档。这也会将整个响应加载到内存中,您可能希望避免这样做。这里也没有使用PIL
,只需将open(image_name,'wb')作为outfile:outfile.write(r.content)
就足够了。PIL
也不在标准库中,这使得它的可移植性稍差。@ZhenyiZhangiter_content
速度慢,因为块大小
太小,如果将其增加到100k,速度会快得多。根据请求作者http://docs.python-requests.org/en/latest/user/quickstart/#binary-响应内容
在您的回答的帮助下,我可以在文本文件中找到数据,我使用的步骤是r2=requests.post(r.url,data);打印r2.内容
。但现在我还想知道文件名
。他们的方法干净吗?--目前,我在头文件--r2.headers['content-disposition']
中找到了文件名,它给出了输出
import requests
from PIL import Image
from io import BytesIO
url = 'your_url'
files = {'file': ("C:/Users/shadow/Downloads/black.jpeg", open('C:/Users/shadow/Downloads/black.jpeg', 'rb'),'image/jpg')}
response = requests.post(url, files=files)
img = Image.open(BytesIO(response.content))
img.show()
img_blob = requests.get(url, timeout=5).content
with open(destination + '/' + title, 'wb') as img_file:
img_file.write(img_blob)