Изтегляне на изображения и други файлове от уеб в 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 и 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(), са низ от байтове (тип байтове).

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 цифри. За повече информация относно метода за форматиране на string str, вижте следната статия.

Освен това тук използваме pprint, за да направим изхода по-лесен за четене.

Екстракт с Красива супа

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

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

from bs4 import BeautifulSoup

url = 'https://bg.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