使用python (urllib/urllib2) 下载图片很慢

Using python (urllib/urllib2) to download images is very slow

我正在尝试从 scryfall.com 下载 magic the gathering cards 的图像。他们提供此 json 文件,其中包含每张卡片的所有信息(包括其图像的 url)。所以我写了一个代码,从 json 文件中读取每个 url,并尝试保存它。问题是,代码的请求部分每张图像 运行 需要超过 5 分钟,我不知道为什么。 (我正在获取的每张图片的大小都小于 100kB,并且可以在浏览器中立即打开)

我试过urllib.urlretrieve,urllib2.urlopen,都是一样的。在 python2 和 python3 上都尝试了 运行。

没有错误消息,代码确实有效,只是花费的时间太长,无法继续使用。

编辑:

a=open("cards.json")
b=a.read()

data=[]
data.append(b)

count=0
for elem in data:
    try:
        content=json.loads(elem)
    except:
        print content
        exit()
    for j in content:
        count=count+1
        if j['layout']=='normal' and j['digital']==False:
            url=str(j['image_uris']['normal'])
            final=url[url.find('normal')+6:]
            print (url)
            print("a")
            i1=urllib.urlretrieve(url)
            print("b")
            i2=i1.read()
            file=open(str(count),'wb')
            file.write(i2)
            file.close()


        if count>5:
            exit()

edit2:link 到 json 我正在使用:https://archive.scryfall.com/json/scryfall-default-cards.json

此代码在 1 秒内获取图像

import requests

url = 'https://img.scryfall.com/cards/normal/front/2/c/2c23b39b-a4d6-4f10-8ced-fa4b1ed2cf74.jpg?1561567651'
r = requests.get(url)

with open('image.jpg', 'wb') as f:
    f.write(r.content)

与此代码相同

import urllib.request

url = 'https://img.scryfall.com/cards/normal/front/2/c/2c23b39b-a4d6-4f10-8ced-fa4b1ed2cf74.jpg?1561567651'
urllib.request.urlretrieve(url, 'image.jpg')

我没有查看更多图片。也许问题是当服务器在短时间内看到来自一个 IP 的太多请求然后阻止它们。


编辑:我用这段代码下载了 10 张图片并显示时间

import urllib.request
import time
import json

print('load json')

start = time.time()
content = json.loads(open("scryfall-default-cards.json").read())
end = time.time()
print('time:', end-start)

# ---

start = time.time()

all_urls = len(content)

urls_to_download = 0
for item in content:
    if item['layout'] == 'normal' and item['digital'] is False:
        urls_to_download += 1

print('urls:', 

all_urls, urls_to_download)

end = time.time()
print('time:', end-start)

# ----

start = time.time()
count = 0
for item in content:
    if item['layout'] == 'normal' and item['digital'] is False:
        count += 1
        url = item['image_uris']['normal']
        name = url.split('?')[0].split('/')[-1]
        print(name)
        urllib.request.urlretrieve(url, 'imgs/' + name)
    if count >= 10:
        break
end = time.time()
print('time:', end-start)

结果

load json
time: 3.9926743507385254
urls: 47237 41805
time: 0.054879188537597656
2c23b39b-a4d6-4f10-8ced-fa4b1ed2cf74.jpg
37bc0128-a8d0-477c-abcf-2bdc9e38b872.jpg
2ae1bb79-a931-4d2e-9cc9-a06862dc5cde.jpg
4889a668-0f01-4447-ad2e-91b329258f22.jpg
5b13ba5a-f4b0-420a-9e4f-a65e57721fa4.jpg
893b309d-5e8f-47fa-9f54-eaf16a5f96e3.jpg
27d30285-7729-4130-a768-71867aefe9b3.jpg
783616d6-e3ea-43fd-97eb-6e4c5a2c711f.jpg
cc101b90-3e17-4beb-a606-3e76088e362c.jpg
36da00e3-3ef6-4ad5-a53d-e71cfdafc1e6.jpg
42e1033b-383e-49b4-875f-ccdc94e08c9d.jpg
time: 2.656561851501465

这是一种非常简单有效的快速抓取这些图像的方法。我没有计时,但也不到一秒。

from urllib import request 

url = 'https://img.scryfall.com/cards/normal/front/2/c/2c23b39b-a4d6-4f10-8ced-fa4b1ed2cf74.jpg?1561567651'

f = open('00000001.jpg', 'wb')
f.write(request.urlopen(url).read())
f.close()