Скачивание картинки через urllib и python

Итак, я пытаюсь создать сценарий 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» до наибольшего числа, которое мне нужно как-то определить. Есть какие-нибудь рекомендации, как это сделать или как правильно загрузить файл?

Спасибо!

РЕДАКТИРОВАТЬ 15/6/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

person Mike    schedule 15.06.2010    source источник
comment
Хорошо, у меня есть все для загрузки! Теперь я застрял с очень неэлегантным решением для определения количества комиксов в сети ... Я в основном запускаю программу для числа, которое, как я знаю, превышает количество комиксов, а затем запускаю исключение, которое возникает, когда комикс не не существует, и когда исключение возникает более двух раз (так как я не думаю, что больше двух комиксов будет отсутствовать), он выходит из программы, думая, что больше нечего загружать. Поскольку у меня нет доступа к веб-сайту, есть ли лучший способ определить, сколько файлов на сайте? Я выложу свой код через секунду.   -  person Mike    schedule 15.06.2010
comment
creativebe.com/icombiner/merge-jpg.html Я использовал эту программу для объединения всех файлы .jpg в один PDF-файл. Отлично работает, и это бесплатно!   -  person Mike    schedule 15.06.2010
comment
Вы можете опубликовать свое решение в качестве ответа и удалить его из вопроса. Посты с вопросами предназначены для того, чтобы задавать вопросы, ответы на посты для ответов :-)   -  person BartoszKP    schedule 24.08.2014
comment
почему это помечено beautifulsoup? Это сообщение отображается в списке beautifulsoup самых популярных вопросов   -  person P0W    schedule 26.11.2016
comment
Если кто-то все еще ищет ... теперь он находится в urllib.request.URLopener ()   -  person Filippo Mazza    schedule 07.07.2017
comment
@ P0W Я удалил обсуждаемый тег.   -  person kmonsoor    schedule 28.12.2017
comment
Настоящий ответ здесь - использовать запросы.   -  person AMC    schedule 01.04.2020


Ответы (18)


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")
person Matthew Flaschen    schedule 15.06.2010
comment
Кажется, что у меня отключено расширение файла при передаче в качестве аргумента (расширение присутствует в исходном URL-адресе). Есть идеи, почему? - person JeffThompson; 02.11.2014
comment
@ ДжеффТомпсон, нет. Работает ли пример (в моем ответе) для вас (для меня он работает с Python 2.7.8)? Обратите внимание, как он явно указывает расширение для локального файла. - person Matthew Flaschen; 03.11.2014
comment
Ваш, да. Думаю, я предполагал, что если расширение файла не указано, расширение файла будет добавлено. В то время это имело для меня смысл, но теперь я думаю, что понимаю, что происходит. - person JeffThompson; 03.11.2014

Для записи, используя библиотеку запросов.

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

Хотя он должен проверять наличие ошибки requests.get ().

person ellimilial    schedule 19.02.2013
comment
Даже если это решение не использует urllib, возможно, вы уже используете библиотеку запросов в своем скрипте python (это был мой случай при поиске этого), поэтому вы можете также использовать ее для получения своих изображений. - person Iam Zesh; 25.04.2014
comment
Спасибо, что разместили этот ответ поверх других. В итоге мне потребовались настраиваемые заголовки, чтобы моя загрузка работала, а указатель на библиотеку запросов значительно сократил для меня процесс работы. - person kuzzooroo; 20.10.2014
comment
Не удалось даже заставить urllib работать в python3. С запросами проблем не было, и он уже загружен! Думаю, это лучший выбор. - person user3023715; 03.11.2017
comment
@ user3023715 в python3 вам необходимо импортировать запрос из urllib см. здесь - person Yassine Sedrani; 13.12.2018

Для Python 3 вам нужно будет импортировать import urllib.request:

import urllib.request 

urllib.request.urlretrieve(url, filename)

для получения дополнительной информации перейдите по ссылке

person HISI    schedule 30.07.2017

Python 3 версия ответа @ DiGMi:

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

Я нашел этот ответ и я редактирую это более надежным способом

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

Из-за этого вы никогда не получите никаких других ресурсов или исключений при загрузке.

person Janith Chinthana    schedule 08.04.2013
comment
Вы должны удалить "я" - person Euphe; 27.03.2016

Если вы знаете, что файлы находятся в том же каталоге dir веб-сайта site и имеют следующий формат: имя_файла_01.jpg, ..., имя_файла_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()
person len    schedule 03.02.2016

Проще всего использовать .read() для чтения частичного или полного ответа, а затем записать его в файл, который вы открыли в заведомо надежном месте.

person Ignacio Vazquez-Abrams    schedule 15.06.2010

Может быть вам нужен User-Agent:

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()
person Alexander    schedule 20.05.2014
comment
Может страница недоступна? - person Alexander; 06.11.2014

Помимо предложения вам внимательно прочитать документацию для retrieve() (http://docs.python.org/library/urllib.html#urllib.URLopener.retrieve), я бы предложил фактически вызвать read() для содержимого ответа, а затем сохранить его в файл по вашему выбору, а не оставлять его в временный файл, который извлекает, создает.

person Gabriel Hurley    schedule 15.06.2010

Все вышеперечисленные коды не позволяют сохранить исходное имя изображения, которое иногда требуется. Это поможет сохранить образы на локальный диск, сохранив исходное имя образа.

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

Попробуйте это для получения дополнительных сведений.

person Ojas    schedule 18.07.2014

Это сработало для меня, используя python 3.

Он получает список URL-адресов из файла csv и начинает их загрузку в папку. Если контент или изображение не существует, он принимает это исключение и продолжает творить чудеса.

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!")
person Victor    schedule 22.02.2018

Более простое решение может быть (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;
person Ayush    schedule 01.02.2017
comment
Будьте осторожны при использовании пустого файла, кроме этого, см. stackoverflow.com/questions/54948548/. - person AMC; 01.04.2020

Согласно urllib.request.urlretrieve - Python 3.9.2 документация, Функция перенесена из модуля 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)

См. Загрузите изображения Google WebP через Делайте снимки экрана с помощью Selenium WebDriver.

person SparkAndShine    schedule 20.02.2021

Как насчет этого:

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()
person gmas80    schedule 30.10.2014

Используя 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")
person Sreekant Shenoy    schedule 11.05.2020

Если вам нужна поддержка прокси, вы можете сделать это:

  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 )
person Eamonn Kenny    schedule 06.03.2018

Другой способ сделать это - использовать библиотеку fastai. Это сработало для меня как прелесть. Я столкнулся с SSL: CERTIFICATE_VERIFY_FAILED Error использованием urlretrieve, поэтому я попробовал это.

url = 'https://www.linkdoesntexist.com/lennon.jpg'
fastai.core.download_url(url,'image1.jpg', show_progress=False)
person Sid    schedule 15.06.2019
comment
Я столкнулся с ошибкой SSL: CERTIFICATE_VERIFY_FAILED stackoverflow.com/questions/27835619/ - person AMC; 01.04.2020

Использование запросов

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)
person Sohan Das    schedule 18.04.2020