Завантажуйте зображення та інші файли з Інтернету на Python (окремо або пакетами)

Бізнес

Нижче пояснюється, як вказати URL-адресу зображення, ZIP, PDF або іншого файлу в Інтернеті в Python, завантажити його та зберегти як локальний файл.

  • Завантажте зображення, вказавши URL-адресу.
    • Приклад коду
    • urllib.request.urlopen():Відкрити URL
    • open():Запис у файл у двійковому режимі
    • Простіший приклад коду
  • Завантажте ZIP-файли, PDF-файли тощо.
  • Витягніть URL-адресу зображення на веб-сторінці.
    • Якщо номер послідовний
    • Екстракт з красивим супом
  • Пакетне завантаження кількох зображень зі списку URL-адрес

Завантажте зображення, вказавши URL-адресу.

Ви можете використовувати стандартну бібліотеку лише для завантаження окремих файлів, вказавши їх URL-адреси; не потрібно додаткової установки.

Приклад коду

Нижче наведено приклад функції, яка завантажує та зберігає файл, вказуючи URL-адресу та шлях призначення, а також його використання. Цей код є трохи багатослівним для пояснення. Нижче наведено простий приклад.

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)

Щоб вказати каталог призначення та зберегти файл з іменем файлу URL, виконайте наступне

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)

Він витягує ім’я файлу з URL-адреси за допомогою os.path.basename() і з’єднує його з каталогом, зазначеним за допомогою os.path.join(), щоб створити шлях призначення.

У наступних розділах описується частина збору даних і частина збереження даних у файлі.

urllib.request.urlopen():Відкрити URL

Використовуйте urllib.request.urlopen(), щоб відкрити URL-адресу та отримати дані. Зауважте, що urllib.urlopen() не підтримується в Python 2.6 і раніше. urllib.request.urlretrieve() ще не застарів, але може статися в майбутньому.

Щоб уникнути зупинки при виникненні винятку, ловіть помилку за допомогою try та крім.

У прикладі імпортується urllib.error, і тільки urllib.error.URLError фіксується явно. Повідомлення про помилку відображатиметься, якщо URL-адреса файлу не існує.

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

Якщо ви хочете також перехоплювати винятки (FileNotFoundError тощо) під час локального збереження, виконайте наступне.
(urllib.error.URLError, FileNotFoundError)

Також можна використовувати сторонню бібліотеку Requests замість стандартної бібліотеки urllib, щоб відкрити URL-адресу та отримати дані.

Записати у файл у двійковому режимі за допомогою open()

Дані, які можна отримати за допомогою urllib.request.urlopen(), є рядком байтів (типу байтів).

Open() з mode=’wb’ як другим аргументом записує дані як двійкові. w означає запис, а b означає двійковий.

Простіший приклад коду

Вкладені з операторами можна писати відразу, розділяючи їх комами.

Використовуючи це, ми можемо написати наступне.

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)

Завантажте ZIP-файли, PDF-файли тощо.

Наразі наведені приклади для завантаження та збереження файлів зображень, але оскільки ми просто відкриваємо файл в Інтернеті та зберігаємо його як локальний файл, ті самі функції можна використовувати для інших типів файлів.

Ви можете завантажувати та зберігати файли, вказавши URL-адресу.

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)

Зауважте, що URL-адреса, зазначена в цій функції, має бути посиланням на сам файл.

Наприклад, у випадку файлу репозиторію GitHub, наступна URL-адреса має розширення pdf, але насправді є сторінкою html. Якщо цю URL-адресу вказано у функції вище, буде завантажено джерело html.

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

Посилання на файл є такою URL-адресою, яку потрібно вказати, якщо ви хочете завантажити та зберегти файл.

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

Існують також випадки, коли доступ обмежується агентом користувача, реферером тощо, що унеможливлює завантаження. Ми не гарантуємо, що всі файли будуть завантажені.

Запити легко використовувати для зміни або додавання заголовків запитів, таких як агент користувача.

Витягніть URL-адресу зображення на веб-сторінці.

Щоб завантажити всі зображення на сторінці одночасно, спочатку витягніть URL-адреси зображень і створіть список.

Якщо номер послідовний

Якщо URL-адреса зображення, яке ви хочете завантажити, є простим порядковим номером, це легко. Якщо URL-адреси є не тільки послідовними номерами, але й мають певну регулярність, легше скласти список URL-адрес відповідно до правил, ніж скребти за допомогою Beautiful Soup (див. нижче).

Використовуйте позначення розуміння списку.

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']

У наведеному вище прикладі {:03} використовується для 3-значного послідовного номера, заповненого нулем; {} використовується, коли заповнення нуля не потрібне, а {:05} використовується для 5-значного числа замість 3-х цифр. Додаткову інформацію про метод форматування рядка str дивіться в наступній статті.

Крім того, тут ми використовуємо pprint, щоб полегшити читання результатів.

Екстракт з красивим супом

Щоб масово витягувати URL-адреси зображень із веб-сторінок, використовуйте Beautiful Soup.

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

from bs4 import BeautifulSoup

url = 'https://uk.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')]

У прикладі витягується URL-адреса мініатюрного зображення цього веб-сайту.

Структура залежить від веб-сторінки, але в основному вона виходить наступним чином.

  • Отримайте список <img> тег об’єктів, вказуючи клас, ідентифікатор тощо блоку, що містить кілька зображень, які потрібно завантажити.
    • soup.find(class_='list').find_all('img')
  • Отримайте URL-адресу зображення з елемента src або елемента data-src у <img> тег.
    • img.get('data-src')

Наведений вище зразок коду є лише прикладом і не гарантується, що він працює.

Пакетне завантаження кількох зображень зі списку URL-адрес

Якщо у вас є список URL-адрес, ви можете просто перетворити його в цикл for і викликати функцію для завантаження та збереження файлу з першою показаною URL-адресою. Через тимчасовий список URL-адрес тут коментується виклик функції 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

Щоб не перевантажувати сервер, я використовую time.sleep() для створення часу очікування для кожного завантаження зображення. Одиниця вимірюється в секундах, тому у наведеному вище прикладі модуль часу імпортується та використовується.

Приклад стосується файлів зображень, але інші типи файлів також можна завантажувати разом, якщо вони вказані в списку.