我试图使用python的请求模块从网络下载并保存一张图像。

下面是我使用的(工作)代码:

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)

你能帮我从请求中使用响应的什么属性吗?


当前回答

这个怎么样,一个快速的解决方案。

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)

其他回答

同意Blairg23的观点,使用urllib.request.urlretrieve是最简单的解决方案之一。

这里我想指出一点。有时它不会下载任何东西,因为请求是通过脚本(bot)发送的,如果你想解析来自谷歌图像或其他搜索引擎的图像,你需要先传递user-agent请求标题,然后再下载图像,否则,请求将被阻止并抛出错误。

传递user-agent,下载镜像:

opener=urllib.request.build_opener()
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582')]
urllib.request.install_opener(opener)

urllib.request.urlretrieve(URL, 'image_name.jpg')

在线IDE中的代码,使用请求,bs4, urllib.requests从谷歌图像中抓取和下载图像。


或者,如果你的目标是从谷歌,Bing, Yahoo!, DuckDuckGo(和其他搜索引擎),然后你可以使用SerpApi。这是一个带有免费计划的付费API。

最大的区别是,不需要弄清楚如何绕过搜索引擎的块,或者如何从HTML或JavaScript中提取某些部分,因为这些已经为最终用户完成了。

要集成的示例代码:

import os, urllib.request
from serpapi import GoogleSearch

params = {
  "api_key": os.getenv("API_KEY"),
  "engine": "google",
  "q": "pexels cat",
  "tbm": "isch"
}

search = GoogleSearch(params)
results = search.get_dict()

print(json.dumps(results['images_results'], indent=2, ensure_ascii=False))

# download images 
for index, image in enumerate(results['images_results']):

    # print(f'Downloading {index} image...')
    
    opener=urllib.request.build_opener()
    opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582')]
    urllib.request.install_opener(opener)

    # saves original res image to the SerpApi_Images folder and add index to the end of file name
    urllib.request.urlretrieve(image['original'], f'SerpApi_Images/original_size_img_{index}.jpg')

-----------
'''
]
  # other images
  {
    "position": 100, # 100 image
    "thumbnail": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQK62dIkDjNCvEgmGU6GGFZcpVWwX-p3FsYSg&usqp=CAU",
    "source": "homewardboundnj.org",
    "title": "pexels-helena-lopes-1931367 - Homeward Bound Pet Adoption Center",
    "link": "https://homewardboundnj.org/upcoming-event/black-cat-appreciation-day/pexels-helena-lopes-1931367/",
    "original": "https://homewardboundnj.org/wp-content/uploads/2020/07/pexels-helena-lopes-1931367.jpg",
    "is_product": false
  }
]
'''

免责声明,我为SerpApi工作。

这可能比使用请求更容易。这是我唯一一次建议不要使用请求来做HTTP的事情。

使用urllib的两个内衬:

>>> import urllib
>>> urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

还有一个叫做wget的Python模块,它非常容易使用。在这里找到。

这说明了设计的简单性:

>>> 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)

这里有一个更友好的答案,仍然使用流媒体。

只需定义这些函数并调用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()的请求内容基于上面的答案。

这是谷歌搜索如何下载带有请求的二进制文件时出现的第一个响应。如果你需要下载带有请求的任意文件,你可以使用:

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)

我的方法是使用回应。内容(blob)并以二进制模式保存到文件中

img_blob = requests.get(url, timeout=5).content
with open(destination + '/' + title, 'wb') as img_file:
     img_file.write(img_blob)

看看我的python项目,根据关键字从unsplash.com下载图像。