Загружать изображения и другие файлы из Интернета в Python (по отдельности или партиями)

Бизнес

Ниже описано, как в Python указать URL изображения, ZIP, PDF или другого файла в Интернете, загрузить его и сохранить как локальный файл.

  • Загрузите изображения, указав 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 и except.

В примере импортируется 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(), представляют собой байтовую строку (тип bytes).

Open() с mode='wb' в качестве второго аргумента записывает данные в двоичном формате. w означает запись, а b — двоичный формат.

Более простой пример кода

Вложенные утверждения with можно записывать сразу, разделяя их запятыми.

Используя это, мы можем написать следующее.

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

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

Легко использовать Requests для изменения или добавления заголовков запроса, таких как user agent.

Извлеките 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-значного номера вместо трех цифр. Более подробную информацию о методе format метода string str см. в следующей статье.

Кроме того, здесь мы используем pprint, чтобы сделать вывод более удобным для чтения.

Отрывок, характеризующий Красивый суп

Для массового извлечения URL-адресов изображений с веб-страниц используйте Beautiful Soup.

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

from bs4 import BeautifulSoup

url = 'https://ru.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>, указав класс, id и т.д. блока, содержащего несколько изображений, которые вы хотите загрузить.
    • 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() для создания времени ожидания для каждой загрузки изображения. Единица измерения — секунды, поэтому в примере выше импортируется и используется модуль time.

Пример относится к файлам изображений, но файлы других типов также можно загружать вместе, если они указаны в списке.

Copied title and URL