Preuzmite slike i druge datoteke s weba u Pythonu (pojedinačno ili u skupinama)

Poslovanje

Sljedeće objašnjava kako odrediti URL slike, ZIP-a, PDF-a ili druge datoteke na webu u Pythonu, preuzeti je i spremiti kao lokalnu datoteku.

  • Preuzmite slike navođenjem URL-a.
    • Primjer koda
    • urllib.request.urlopen():Otvori URL
    • open():Pišite u datoteku u binarnom načinu
    • Jednostavniji primjer koda
  • Preuzmite ZIP datoteke, PDF datoteke itd.
  • Izdvojite URL slike na web stranici.
    • Ako je broj sekvencijalan
    • Ekstrakt s prekrasnom juhom
  • Skupno preuzmite više slika s popisa URL-ova

Preuzmite slike navođenjem URL-a.

Standardnu ​​biblioteku možete koristiti samo za preuzimanje pojedinačnih datoteka navodeći njihove URL-ove; nije potrebna dodatna instalacija.

Primjer koda

Slijedi primjer funkcije koja preuzima i sprema datoteku navođenjem URL-a i odredišne ​​staze te njezine upotrebe. Ovaj kod je malo opsežan radi objašnjenja. Jednostavan primjer dat je u nastavku.

import os
import pprint
import time
import urllib.error
import urllib.request

def download_file(url, dst_path):
    try:
        with urllib.request.urlopen(url) as web_file:
            data = web_file.read()
            with open(dst_path, mode='wb') as local_file:
                local_file.write(data)
    except urllib.error.URLError as e:
        print(e)
url = 'https://www.python.org/static/img/python-logo.png'
dst_path = 'data/temp/py-logo.png'
download_file(url, dst_path)

Da biste odredili odredišni direktorij i spremili datoteku s nazivom URL datoteke, učinite sljedeće

def download_file_to_dir(url, dst_dir):
    download_file(url, os.path.join(dst_dir, os.path.basename(url)))

dst_dir = 'data/temp'
download_file_to_dir(url, dst_dir)

Izvlači naziv datoteke iz URL-a pomoću os.path.basename() i pridružuje ga direktoriju specificiranom s os.path.join() kako bi se generirao odredišni put.

Sljedeći odjeljci opisuju dio prikupljanja podataka i dio spremanja podataka kao datoteke.

urllib.request.urlopen():Otvori URL

Koristite urllib.request.urlopen() da otvorite URL i dohvatite podatke. Imajte na umu da je urllib.urlopen() zastario u Pythonu 2.6 i ranijim verzijama. urllib.request.urlretrieve() još nije zastario, ali može biti u budućnosti.

Kako biste izbjegli zaustavljanje kada se dogodi iznimka, uhvatite pogrešku pomoću pokušaja i osim.

U primjeru, urllib.error je uvezen i samo je urllib.error.URLError eksplicitno zahvaćen. Poruka o pogrešci će se prikazati kada URL datoteke ne postoji.

url_error = 'https://www.python.org/static/img/python-logo_xxx.png'
download_file_to_dir(url_error, dst_dir)
# HTTP Error 404: Not Found

Ako želite također uhvatiti iznimke (FileNotFoundError, itd.) prilikom lokalnog spremanja, učinite sljedeće.
(urllib.error.URLError, FileNotFoundError)

Također je moguće koristiti zahtjeve biblioteke treće strane umjesto standardne biblioteke urllib za otvaranje url-a i dobivanje podataka.

Pisanje u datoteku u binarnom načinu u open()

Podaci koji se mogu dobiti pomoću urllib.request.urlopen() je niz bajtova (tip bajtova).

Open() s mode=’wb’ kao drugim argumentom zapisuje podatke kao binarne. w znači pisanje i b znači binarno.

Jednostavniji primjer koda

Ugniježđeni iskazi mogu se pisati odjednom, odvojeni zarezima.

Koristeći ovo, možemo napisati sljedeće.

def download_file(url, dst_path):
    try:
        with urllib.request.urlopen(url) as web_file, open(dst_path, 'wb') as local_file:
            local_file.write(web_file.read())
    except urllib.error.URLError as e:
        print(e)

Preuzmite ZIP datoteke, PDF datoteke itd.

Dosadašnji primjeri su za preuzimanje i spremanje slikovnih datoteka, ali budući da jednostavno otvaramo datoteku na webu i spremamo je kao lokalnu datoteku, iste se funkcije mogu koristiti i za druge vrste datoteka.

Datoteke možete preuzeti i spremati navođenjem URL-a.

url_zip = 'https://from-locas.com/sample_header.csv.zip'
download_file_to_dir(url_zip, dst_dir)

url_xlsx = 'https://from-locas/sample.xlsx'
download_file_to_dir(url_xlsx, dst_dir)

url_pdf = 'https://from-locas/sample1.pdf'
download_file_to_dir(url_pdf, dst_dir)

Imajte na umu da URL naveden u ovoj funkciji mora biti veza na samu datoteku.

Na primjer, u slučaju datoteke repozitorija GitHub, sljedeći URL ima pdf ekstenziju, ali je zapravo html stranica. Ako je ovaj URL naveden u gornjoj funkciji, html izvor će se preuzeti.

  • https://github.com/from-locals/python-snippets/blob/master/notebook/data/src/pdf/sample1.pdf

Veza na datotečni entitet je sljedeći URL, koji trebate navesti ako želite preuzeti i spremiti datoteku.

  • https://github.com/from-locals/python-snippets/raw/master/notebook/data/src/pdf/sample1.pdf

Postoje i slučajevi u kojima je pristup ograničen korisničkim agentom, preporukom itd., što onemogućuje preuzimanje. Ne jamčimo da će sve datoteke biti preuzete.

Lako je koristiti zahtjeve za promjenu ili dodavanje zaglavlja zahtjeva kao što je korisnički agent.

Izdvojite URL slike na web stranici.

Za preuzimanje svih slika na stranici odjednom, prvo izdvojite URL-ove slika i izradite popis.

Ako je broj sekvencijalan

Ako je URL slike koju želite preuzeti jednostavan redni broj, to je jednostavno. Ako URL-ovi nisu samo uzastopni brojevi, već imaju i određenu pravilnost, lakše je napraviti popis URL-ova u skladu s pravilima, a ne strugati s Lijepom juhom (vidi dolje).

Koristite zapis za razumijevanje popisa.

url_list = ['https://example.com/basedir/base_{:03}.jpg'.format(i) for i in range(5)]
pprint.pprint(url_list)
# ['https://example.com/basedir/base_000.jpg',
#  'https://example.com/basedir/base_001.jpg',
#  'https://example.com/basedir/base_002.jpg',
#  'https://example.com/basedir/base_003.jpg',
#  'https://example.com/basedir/base_004.jpg']

U gornjem primjeru, {:03} se koristi za 3-znamenkasti sekvencijalni broj ispunjen nulom; {} se koristi kada popunjavanje nule nije potrebno, a {:05} se koristi za 5-znamenkasti broj umjesto 3 znamenke. Za više informacija o metodi formatiranja string str, pogledajte sljedeći članak.

Također, ovdje koristimo pprint za lakše čitanje izlaza.

Ekstrakt s prekrasnom juhom

Za masovno izdvajanje URL-ova slika s web-stranica upotrijebite Lijepu juhu.

import os
import time
import urllib.error
import urllib.request

from bs4 import BeautifulSoup

url = 'https://hr.from-locals.com/'
ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) '\
     'AppleWebKit/537.36 (KHTML, like Gecko) '\
     'Chrome/55.0.2883.95 Safari/537.36 '

req = urllib.request.Request(url, headers={'User-Agent': ua})
html = urllib.request.urlopen(req)

soup = BeautifulSoup(html, "html.parser")

url_list = [img.get('data-src') for img in soup.find(class_='list').find_all('img')]

U primjeru se izdvaja URL minijature ove web stranice.

Struktura se razlikuje ovisno o web stranici, ali se u osnovi dobiva na sljedeći način.

  • Nabavite popis <img> označite objekte navodeći klasu, id, itd. bloka koji sadrži više slika koje želite preuzeti.
    • soup.find(class_='list').find_all('img')
  • Nabavite URL slike iz elementa src ili elementa data-src u <img> označiti.
    • img.get('data-src')

Gornji primjer koda je samo primjer i nije zajamčeno da će raditi.

Skupno preuzmite više slika s popisa URL-ova

Ako imate popis URL-ova, možete ga jednostavno pretvoriti u for petlju i pozvati funkciju za preuzimanje i spremanje datoteke s prvim prikazanim URL-om. Zbog privremenog popisa URL-ova, ovdje je komentiran poziv funkcije download_image_dir().

download_dir = 'data/temp'
sleep_time_sec = 1

for url in url_list:
    print(url)
#     download_file_dir(url, download_dir)
    time.sleep(sleep_time_sec)
# https://example.com/basedir/base_000.jpg
# https://example.com/basedir/base_001.jpg
# https://example.com/basedir/base_002.jpg
# https://example.com/basedir/base_003.jpg
# https://example.com/basedir/base_004.jpg

Kako ne bih preopteretio poslužitelj, koristim time.sleep() za stvaranje vremena čekanja za svako preuzimanje slike. Jedinica je u sekundama, pa se u gornjem primjeru uvozi i koristi vremenski modul.

Primjer je za slikovne datoteke, ali i druge vrste datoteka mogu se preuzimati zajedno, sve dok su navedene.