【问题标题】:Downloading a picture via urllib and python通过urllib和python下载图片
【发布时间】:2011-03-03 20:01:09
【问题描述】:

所以我正在尝试制作一个 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'增加到最大数字,我必须以某种方式确定。有关执行此操作的最佳方法或如何正确下载文件的任何建议?

谢谢!

2010 年 6 月 15 日编辑

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

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

【问题讨论】:

  • 好的,我都下载好了!现在我陷入了一个非常不雅的解决方案来确定有多少漫画在线......我基本上将程序运行到我知道超过漫画数量的数字,然后在漫画没有出现时运行异常'不存在,并且当异常出现两次以上时(因为我认为不会丢失超过两本漫画),它会退出程序,认为没有更多可下载的了。由于我无法访问该网站,是否有确定网站上有多少文件的最佳方法?稍后我会发布我的代码。
  • creativebe.com/icombiner/merge-jpg.html 我使用该程序将所有 .jpg 文件合并为一个 PDF。效果很棒,而且是免费的!
  • 考虑将您的解决方案作为答案发布,并将其从问题中删除。问题帖子用于提问,回答帖子用于答案:-)
  • 为什么用 beautifulsoup 标记?这篇文章显示在顶部beautifulsoup问题列表中
  • @P0W 我已经删除了讨论的标签。

标签: python urllib2 urllib


【解决方案1】:

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,没有。该示例(在我的回答中)是否适合您(它适用于 Python 2.7.8)?请注意它是如何为本地文件显式指定扩展名的。
  • 你的,是的。我想我假设如果没有给出文件扩展名,则将附加文件的扩展名。当时这对我来说是有道理的,但我想现在我明白发生了什么。
  • 当我想将它下载到当前文件时,这似乎不起作用...为什么?
  • 似乎如果你从 pycharm 的控制台运行它,谁知道当前文件夹在哪里......
【解决方案2】:
import urllib
f = open('00000001.jpg','wb')
f.write(urllib.urlopen('http://www.gunnerkrigg.com//comics/00000001.jpg').read())
f.close()

【讨论】:

    【解决方案3】:

    仅作记录,使用请求库。

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

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

    【讨论】:

    • 即使这个解决方案没有使用 urllib,你可能已经在你的 python 脚本中使用了 requests 库(这是我在搜索这个时的情况),所以你可能也想使用它来拿你的照片。
    • 感谢您将此答案发布在其他答案之上。我最终需要自定义标头才能让我的下载工作,并且指向请求库的指针大大缩短了让一切为我工作的过程。
    • 甚至无法让 urllib 在 python3 中工作。请求没有问题,并且已经加载!我认为是更好的选择。
    • @user3023715 在 python3 中你需要从 urllib 导入请求 see here
    【解决方案4】:

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

    import urllib.request 
    
    urllib.request.urlretrieve(url, filename)
    

    更多信息请查看link

    【讨论】:

      【解决方案5】:

      @DiGMi 答案的 Python 3 版本:

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

      【讨论】:

        【解决方案6】:

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

        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
        

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

        【讨论】:

        • 你应该删除'self'
        【解决方案7】:

        如果您知道这些文件与网站site 位于同一目录dir 并具有以下格式: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()
        

        【讨论】:

          【解决方案8】:

          最简单的方法是使用.read() 读取部分或全部响应,然后将其写入您在已知正确位置打开的文件中。

          【讨论】:

            【解决方案9】:

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

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

            【讨论】:

            • 可能页面不可用?
            【解决方案10】:

            除了建议您仔细阅读 retrieve() 的文档 (http://docs.python.org/library/urllib.html#urllib.URLopener.retrieve),我还建议您在响应内容上实际调用 read(),然后将其保存到您选择的文件中,而不是离开它在检索创建的临时文件中。

            【讨论】:

              【解决方案11】:

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

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

              Try this 了解更多详情。

              【讨论】:

                【解决方案12】:

                这对我使用 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!")
                

                【讨论】:

                  【解决方案13】:

                  一个更简单的解决方案可能是(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;
                  

                  【讨论】:

                  【解决方案14】:

                  使用 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")
                  

                  【讨论】:

                    【解决方案15】:

                    根据urllib.request.urlretrieve — Python 3.9.2 documentation,该函数是从Python 2 模块urllib(而不是urllib2)移植而来的。它可能会在将来的某个时候被弃用。

                    因此,使用requests.get(url, params=None, **kwargs) 可能会更好。这是一个 MWE。

                    import requests
                     
                    url = 'http://example.com/example.jpg'
                    
                    response = requests.get(url)
                    
                    with open(filename, "wb") as f:
                        f.write(response.content)
                    

                    请参阅Downlolad Google’s WebP Images via Take Screenshots with Selenium WebDriver

                    【讨论】:

                      【解决方案16】:

                      这个呢:

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

                      【讨论】:

                        【解决方案17】:

                        如果您需要代理支持,您可以这样做:

                          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 )
                        

                        【讨论】:

                          【解决方案18】:

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

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

                          【讨论】:

                          【解决方案19】:

                          使用请求

                          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)
                          

                          【讨论】:

                            【解决方案20】:

                            而如果你想下载类似网站目录结构的图片,你可以这样做:

                                result_path = './result/'
                                soup = BeautifulSoup(self.file, 'css.parser')
                                for image in soup.findAll("img"):
                                    image["name"] = image["src"].split("/")[-1]
                                    image['path'] = image["src"].replace(image["name"], '')
                                    os.makedirs(result_path + image['path'], exist_ok=True)
                                    if image["src"].lower().startswith("http"):
                                        urlretrieve(image["src"], result_path + image["src"][1:])
                                    else:
                                        urlretrieve(url + image["src"], result_path + image["src"][1:])
                            

                            【讨论】:

                              猜你喜欢
                              • 2011-05-20
                              • 1970-01-01
                              • 2018-02-11
                              • 1970-01-01
                              • 2020-10-29
                              • 2013-11-27
                              • 2020-10-08
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多