通过urllib和python下载图片


182

因此,我试图制作一个Python脚本来下载网络漫画,并将其放入桌面上的文件夹中。我在这里发现了一些类似的程序,它们执行相似的操作,但是并没有完全满足我的需要。我发现最相似的代码就在这里(http://bytes.com/topic/python/answers/850927-problem-using-urllib-download-images)。我尝试使用此代码:

>>> import urllib
>>> image = urllib.URLopener()
>>> image.retrieve("http://www.gunnerkrigg.com//comics/00000001.jpg","00000001.jpg")
('00000001.jpg', <httplib.HTTPMessage instance at 0x1457a80>)

然后,我在计算机上搜索了文件“ 00000001.jpg”,但我发现的只是它的缓存图片。我什至不确定它是否已将文件保存到我的计算机中。一旦我了解了如何下载文件,我想我就会处理其余的事情。本质上,只需要使用for循环并在'00000000'。'jpg'处拆分字符串,然后将'00000000'递增至最大数,我必须以某种方式确定。关于最佳方法或正确下载文件的任何建议?

谢谢!

编辑6/15/10

这是完成的脚本,它将文件保存到您选择的任何目录中。由于某种奇怪的原因,文件没有下载,而只是下载了。任何有关如何清理它的建议将不胜感激。我目前正在研究如何查找网站上存在的漫画,因此我可以获取最新的漫画,而不是在引发一定数量的异常后退出程序。

import urllib
import os

comicCounter=len(os.listdir('/file'))+1  # reads the number of files in the folder to start downloading at the next comic
errorCount=0

def download_comic(url,comicName):
    """
    download a comic in the form of

    url = http://www.example.com
    comicName = '00000000.jpg'
    """
    image=urllib.URLopener()
    image.retrieve(url,comicName)  # download comicName at URL

while comicCounter <= 1000:  # not the most elegant solution
    os.chdir('/file')  # set where files download to
        try:
        if comicCounter < 10:  # needed to break into 10^n segments because comic names are a set of zeros followed by a number
            comicNumber=str('0000000'+str(comicCounter))  # string containing the eight digit comic number
            comicName=str(comicNumber+".jpg")  # string containing the file name
            url=str("http://www.gunnerkrigg.com//comics/"+comicName)  # creates the URL for the comic
            comicCounter+=1  # increments the comic counter to go to the next comic, must be before the download in case the download raises an exception
            download_comic(url,comicName)  # uses the function defined above to download the comic
            print url
        if 10 <= comicCounter < 100:
            comicNumber=str('000000'+str(comicCounter))
            comicName=str(comicNumber+".jpg")
            url=str("http://www.gunnerkrigg.com//comics/"+comicName)
            comicCounter+=1
            download_comic(url,comicName)
            print url
        if 100 <= comicCounter < 1000:
            comicNumber=str('00000'+str(comicCounter))
            comicName=str(comicNumber+".jpg")
            url=str("http://www.gunnerkrigg.com//comics/"+comicName)
            comicCounter+=1
            download_comic(url,comicName)
            print url
        else:  # quit the program if any number outside this range shows up
            quit
    except IOError:  # urllib raises an IOError for a 404 error, when the comic doesn't exist
        errorCount+=1  # add one to the error count
        if errorCount>3:  # if more than three errors occur during downloading, quit the program
            break
        else:
            print str("comic"+ ' ' + str(comicCounter) + ' ' + "does not exist")  # otherwise say that the certain comic number doesn't exist
print "all comics are up to date"  # prints if all comics are downloaded

好的,我把它们都下载了!现在,我采用了一种非常精致的解决方案来确定在线有多少漫画...我基本上是将程序运行到我知道超出漫画数量的数量,然后运行一个异常,当漫画没有出现它不存在,并且当异常出现两次以上时(因为我认为不会丢失两个以上的漫画),它退出程序,认为没有更多可下载的内容。由于我无权访问该网站,是否有最佳方法确定该网站上有多少个文件?我将在稍后发布我的代码。
Mike

creativebe.com/icombiner/merge-jpg.html 我使用该程序将所有.jpg文件合并为一个PDF。效果很棒,而且是免费的!
Mike

6
考虑发布解决方案作为答案,然后将其从问题中删除。问题帖用于提问,答案帖用于答案:-)
BartoszKP 2014年

为什么用标记beautifulsoup?这篇文章出现在最重要的beautifulsoup问题列表中
P0W

1
@ P0W我已经删除了讨论的标签。
kmonsoor

Answers:


250

Python 2

使用urllib.urlretrieve

import urllib
urllib.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")

Python 3

使用urllib.request.urlretrieve(Python 3旧界面的一部分,工作原理完全相同)

import urllib.request
urllib.request.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")

当作为参数传递时,似乎为我切断了文件扩展名(该扩展名存在于原始URL中)。知道为什么吗?
JeffThompson 2014年

1
是的,是的。我想我假设如果没有给出文件扩展名,则文件的扩展名将被附加。当时对我来说很有意义,但现在我想我知道发生了什么。
JeffThompson,2014年

65
对于Python 3的注释,您需要导入[url.request](docs.python.org/3.0/library/…):import urllib.request urllib.request.retrieve("http://...")
wasabigeek 2015年


18
请注意,对于Python 3,它实际上是import urllib.request urllib.request.urlretrieve("http://...jpg", "1.jpg")。这是urlretrieve现在的3.x中的
user1032613 '18

81
import urllib
f = open('00000001.jpg','wb')
f.write(urllib.urlopen('http://www.gunnerkrigg.com//comics/00000001.jpg').read())
f.close()

68

仅作记录,使用请求库。

import requests
f = open('00000001.jpg','wb')
f.write(requests.get('http://www.gunnerkrigg.com//comics/00000001.jpg').content)
f.close()

虽然它应该检查request.get()错误。


1
即使此解决方案未使用urllib,您可能已经在python脚本中使用了请求库(这是我在搜索此脚本时的情况),因此您可能还希望使用它来获取图片。
Iam Zesh 2014年

感谢您将此答案发布在其他答案之上。我最终需要自定义标头才能使下载正常工作,而指向请求库的指针大大缩短了使一切正常运行的过程。
kuzzooroo 2014年

甚至无法让urllib在python3中工作。请求没有问题,并且已经加载!我认为更好的选择。
user3023715 '17

@ user3023715在python3中,您需要从urllib导入请求,请参见此处
Yassine Sedrani,

34

对于Python 3,您需要导入import urllib.request

import urllib.request 

urllib.request.urlretrieve(url, filename)

有关更多信息,请查看链接



10

我找到了这个答案,并以更可靠的方式对其进行了编辑

def download_photo(self, img_url, filename):
    try:
        image_on_web = urllib.urlopen(img_url)
        if image_on_web.headers.maintype == 'image':
            buf = image_on_web.read()
            path = os.getcwd() + DOWNLOADED_IMAGE_PATH
            file_path = "%s%s" % (path, filename)
            downloaded_image = file(file_path, "wb")
            downloaded_image.write(buf)
            downloaded_image.close()
            image_on_web.close()
        else:
            return False    
    except:
        return False
    return True

由此,您在下载时永远不会获得任何其他资源或异常。


1
您应该删除“自我”
Euphe

8

如果您知道这些文件位于dir网站的同一目录中site并且具有以下格式:filename_01.jpg,...,filename_10.jpg,则下载所有文件:

import requests

for x in range(1, 10):
    str1 = 'filename_%2.2d.jpg' % (x)
    str2 = 'http://site/dir/filename_%2.2d.jpg' % (x)

    f = open(str1, 'wb')
    f.write(requests.get(str2).content)
    f.close()


5

也许您需要“用户代理”:

import urllib2
opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36')]
response = opener.open('http://google.com')
htmlData = response.read()
f = open('file.txt','w')
f.write(htmlData )
f.close()

也许页面不可用?
亚历山大


3

以上所有代码均不允许保留原始图像名称,有时这是必需的。这将有助于将图像保存到本地驱动器,并保留原始图像名称

    IMAGE = URL.rsplit('/',1)[1]
    urllib.urlretrieve(URL, IMAGE)

试试这个以获得更多细节。


3

这对我使用python 3。

它从csv文件获取URL列表,然后开始将它们下载到文件夹中。如果内容或图像不存在,它将采用该异常并继续使其神奇。

import urllib.request
import csv
import os

errorCount=0

file_list = "/Users/$USER/Desktop/YOUR-FILE-TO-DOWNLOAD-IMAGES/image_{0}.jpg"

# CSV file must separate by commas
# urls.csv is set to your current working directory make sure your cd into or add the corresponding path
with open ('urls.csv') as images:
    images = csv.reader(images)
    img_count = 1
    print("Please Wait.. it will take some time")
    for image in images:
        try:
            urllib.request.urlretrieve(image[0],
            file_list.format(img_count))
            img_count += 1
        except IOError:
            errorCount+=1
            # Stop in case you reach 100 errors downloading images
            if errorCount>100:
                break
            else:
                print ("File does not exist")

print ("Done!")

2

一个更简单的解决方案可能是(python 3):

import urllib.request
import os
os.chdir("D:\\comic") #your path
i=1;
s="00000000"
while i<1000:
    try:
        urllib.request.urlretrieve("http://www.gunnerkrigg.com//comics/"+ s[:8-len(str(i))]+ str(i)+".jpg",str(i)+".jpg")
    except:
        print("not possible" + str(i))
    i+=1;

小心使用裸机,除非那样,请参阅stackoverflow.com/questions/54948548/…
AMC

1

那这个呢:

import urllib, os

def from_url( url, filename = None ):
    '''Store the url content to filename'''
    if not filename:
        filename = os.path.basename( os.path.realpath(url) )

    req = urllib.request.Request( url )
    try:
        response = urllib.request.urlopen( req )
    except urllib.error.URLError as e:
        if hasattr( e, 'reason' ):
            print( 'Fail in reaching the server -> ', e.reason )
            return False
        elif hasattr( e, 'code' ):
            print( 'The server couldn\'t fulfill the request -> ', e.code )
            return False
    else:
        with open( filename, 'wb' ) as fo:
            fo.write( response.read() )
            print( 'Url saved as %s' % filename )
        return True

##

def main():
    test_url = 'http://cdn.sstatic.net/stackoverflow/img/favicon.ico'

    from_url( test_url )

if __name__ == '__main__':
    main()

0

如果您需要代理支持,则可以执行以下操作:

  if needProxy == False:
    returnCode, urlReturnResponse = urllib.urlretrieve( myUrl, fullJpegPathAndName )
  else:
    proxy_support = urllib2.ProxyHandler({"https":myHttpProxyAddress})
    opener = urllib2.build_opener(proxy_support)
    urllib2.install_opener(opener)
    urlReader = urllib2.urlopen( myUrl ).read() 
    with open( fullJpegPathAndName, "w" ) as f:
      f.write( urlReader )

0

另一种方法是通过fastai库。这对我来说就像是一种魅力。我正面临着一个SSL: CERTIFICATE_VERIFY_FAILED Error使用,urlretrieve所以我尝试了。

url = 'https://www.linkdoesntexist.com/lennon.jpg'
fastai.core.download_url(url,'image1.jpg', show_progress=False)

CERTIFICATE_VERIFY_FAILED错误:我正面临着SSL stackoverflow.com/questions/27835619/...
AMC

0

使用请求

import requests
import shutil,os

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
currentDir = os.getcwd()
path = os.path.join(currentDir,'Images')#saving images to Images folder

def ImageDl(url):
    attempts = 0
    while attempts < 5:#retry 5 times
        try:
            filename = url.split('/')[-1]
            r = requests.get(url,headers=headers,stream=True,timeout=5)
            if r.status_code == 200:
                with open(os.path.join(path,filename),'wb') as f:
                    r.raw.decode_content = True
                    shutil.copyfileobj(r.raw,f)
            print(filename)
            break
        except Exception as e:
            attempts+=1
            print(e)

if __name__ == '__main__':
    ImageDl(url)

0

使用urllib,您可以立即完成此操作。

import urllib.request

opener=urllib.request.build_opener()
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')]
urllib.request.install_opener(opener)

urllib.request.urlretrieve(URL, "images/0.jpg")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.