Pobieranie zdjęcia przez urllib i python

182

Staram się więc utworzyć skrypt w języku Python, który pobierze webcomiki i umieści je w folderze na pulpicie. Znalazłem tutaj kilka podobnych programów, które robią coś podobnego, ale nic podobnego do tego, czego potrzebuję. Ten, który najbardziej podobał mi się, znajduje się tutaj ( http://bytes.com/topic/python/answers/850927-problem-using-urllib-download-images ). Próbowałem użyć tego kodu:

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

Następnie przeszukałem komputer w poszukiwaniu pliku „00000001.jpg”, ale wszystko, co znalazłem, to jego buforowane zdjęcie. Nie jestem nawet pewien, czy zapisał plik na moim komputerze. Gdy zrozumiem, jak pobrać plik, myślę, że wiem, jak sobie z tym poradzić. Zasadniczo wystarczy użyć pętli for i podzielić ciąg na „00000000”. „Jpg” i zwiększyć „00000000” do największej liczby, którą musiałbym jakoś określić. Wszelkie zalecenia dotyczące najlepszego sposobu wykonania tego zadania lub prawidłowego pobrania pliku?

Dzięki!

EDYCJA 6/15/10

Oto gotowy skrypt, który zapisuje pliki w dowolnym wybranym katalogu. Z jakiegoś dziwnego powodu pliki nie były pobierane i właśnie to zrobiły. Wszelkie sugestie dotyczące tego, jak to wyczyścić, byłyby bardzo mile widziane. Obecnie pracuję nad tym, jak dowiedzieć się, że na stronie istnieje wiele komiksów, dzięki czemu mogę uzyskać najnowszą, zamiast wyłączania programu po wystąpieniu pewnej liczby wyjątków.

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
Mikrofon
źródło
Ok, mam je wszystkie do pobrania! Teraz utknąłem z bardzo nieelegacyjnym rozwiązaniem do określania, ile komiksów jest online ... Zasadniczo uruchamiam program do liczby, o której wiem, że jest ponad liczbę komiksów, a następnie uruchamiam wyjątek, który pojawia się, gdy komiks nie działa istnieje, a kiedy wyjątek pojawia się więcej niż dwa razy (ponieważ nie sądzę, aby zabrakło więcej niż dwóch komiksów), program wychodzi z programu, myśląc, że nie ma już więcej do pobrania. Ponieważ nie mam dostępu do strony internetowej, czy istnieje najlepszy sposób, aby określić, ile plików jest w witrynie? Wyślę kod za sekundę.
Mike
creativebe.com/icombiner/merge-jpg.html Użyłem tego programu do scalenia wszystkich plików .jpg w jednym pliku PDF. Działa niesamowicie i jest bezpłatny!
Mike
7
Rozważ opublikowanie swojego rozwiązania jako odpowiedzi i usunięcie go z pytania. Posty z pytaniami służą do zadawania pytań, odpowiedzi do postów z odpowiedziami :-)
BartoszKP
dlaczego jest to oznaczone beautifulsoup? Ten post pojawia się na liście najważniejszych beautifulsouppytań
P0W,
1
@ P0W Usunąłem omawiany tag.
kmonsoor

Odpowiedzi:

252

Python 2

Korzystanie z urllib.urlretrieve

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

Python 3

Korzystanie z urllib.request.urlretrieve (część starszego interfejsu Python 3 działa dokładnie tak samo)

import urllib.request
urllib.request.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")
Matthew Flaschen
źródło
Wydaje mi się, że odcina mi rozszerzenie pliku, gdy jest przekazywane jako argument (rozszerzenie jest obecne w oryginalnym adresie URL). Masz pomysł, dlaczego?
JeffThompson
1
Tak, tak. Myślę, że założyłem, że jeśli nie podano rozszerzenia pliku, rozszerzenie pliku zostanie dołączone. Miałem wtedy sens, ale myślę, że teraz rozumiem, co się dzieje.
JeffThompson
65
Uwaga do Pythona 3 musisz zaimportować [url.request] ( docs.python.org/3.0/library/… ):import urllib.request urllib.request.retrieve("http://...")
wasabigeek
1
Zauważ, że lista docs 3 w Pythonie retrieve () jako część „Legacy Interface” i mówi, że w przyszłości może stać się przestarzała.
Nathan Wailes,
18
Uwaga dotycząca Pythona 3 jest w rzeczywistości import urllib.request urllib.request.urlretrieve("http://...jpg", "1.jpg"). Jest urlretrieveteraz od 3.x.
user1032613,
81
import urllib
f = open('00000001.jpg','wb')
f.write(urllib.urlopen('http://www.gunnerkrigg.com//comics/00000001.jpg').read())
f.close()
DiGMi
źródło
69

Dla przypomnienia, używając biblioteki żądań.

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

Chociaż powinien sprawdzić, czy nie występuje błąd requests.get ().

ellimilial
źródło
1
Nawet jeśli to rozwiązanie nie korzysta z urllib, być może już korzystasz z biblioteki żądań już w skrypcie Pythona (tak było w moim przypadku podczas szukania tego), więc możesz chcieć go również użyć, aby uzyskać swoje zdjęcia.
Iam Zesh,
Dziękujemy za opublikowanie tej odpowiedzi na innych. Skończyło się na tym, że potrzebowałem niestandardowych nagłówków, aby moje pobieranie działało, a wskaźnik do biblioteki żądań znacznie skrócił proces sprawiania, że ​​wszystko działało dla mnie znacznie.
kuzzooroo,
Nie można nawet uzyskać urllib do pracy w python3. Żądania nie miały problemów i są już załadowane! Zdecydowanie lepszy wybór.
user3023715,
@ user3023715 w python3 musisz zaimportować żądanie z urllib patrz tutaj
Yassine Sedrani
34

W przypadku Python 3 musisz zaimportować import urllib.request:

import urllib.request 

urllib.request.urlretrieve(url, filename)

po więcej informacji sprawdź link

HISI
źródło
15

Wersja @ DiGMi w wersji 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()
Dennis Golomazov
źródło
10

Znalazłem tę odpowiedź i edytuję ją w bardziej niezawodny sposób

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

Dzięki temu nigdy nie otrzymujesz żadnych innych zasobów ani wyjątków podczas pobierania.

Janith Chinthana
źródło
1
Powinieneś usunąć „ja”
Euphe
8

Jeśli wiesz, że pliki znajdują się w tym samym katalogu dirwitryny sitei mają następujący format: nazwa_pliku_01.jpg, ..., nazwa_pliku10.jpg, a następnie pobierz je wszystkie:

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()
Len
źródło
7

Najłatwiej jest po prostu użyć .read()do odczytania częściowej lub całkowitej odpowiedzi, a następnie zapisać ją w pliku otwartym w znanej dobrej lokalizacji.

Ignacio Vazquez-Abrams
źródło
5

Może potrzebujesz „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()
Alexander
źródło
Może strona jest niedostępna?
Alexander,
3

Wszystkie powyższe kody nie pozwalają zachować oryginalnej nazwy obrazu, która czasem jest wymagana. Pomoże to w zapisaniu obrazów na dysku lokalnym, zachowując oryginalną nazwę obrazu

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

Spróbuj tego, aby uzyskać więcej informacji.

Ojas
źródło
3

To działało dla mnie przy użyciu Pythona 3.

Pobiera listę adresów URL z pliku csv i rozpoczyna pobieranie ich do folderu. Jeśli treść lub obraz nie istnieje, bierze ten wyjątek i kontynuuje swoją magię.

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!")
Zwycięzca
źródło
2

Prostszym rozwiązaniem może być (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;
Ayush
źródło
Bądź ostrożny używając nagie z wyjątkiem takiego, patrz stackoverflow.com/questions/54948548/... .
AMC
1

A co z tym:

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()
gmas80
źródło
0

Jeśli potrzebujesz wsparcia proxy, możesz to zrobić:

  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 )
Eamonn Kenny
źródło
0

Innym sposobem jest skorzystanie z biblioteki fastai. To działało dla mnie jak urok. Stawałem czoła SSL: CERTIFICATE_VERIFY_FAILED Errorużywaniu, urlretrievewięc spróbowałem.

url = 'https://www.linkdoesntexist.com/lennon.jpg'
fastai.core.download_url(url,'image1.jpg', show_progress=False)
Sid
źródło
Miałem do czynienia z SSL: CERTIFICATE_VERIFY_FAILED Błąd stosoverflow.com/questions/27835619/...
AMC
0

Korzystanie z wniosków

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)
Sohan Das
źródło
0

Za pomocą urllib możesz to zrobić natychmiast.

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")
Sreekant Shenoy
źródło