Tải xuống hình ảnh và các tệp khác từ web bằng Python (riêng lẻ hoặc theo lô)

Kinh doanh

Phần sau giải thích cách chỉ định URL của hình ảnh, ZIP, PDF hoặc tệp khác trên Web bằng Python, tải xuống và lưu dưới dạng tệp cục bộ.

  • Tải xuống hình ảnh bằng cách chỉ định URL.
    • Mã ví dụ
    • urllib.request.urlopen():Mở URL
    • open():Ghi vào tệp ở chế độ nhị phân
    • Một ví dụ mã đơn giản hơn
  • Tải xuống tệp ZIP, tệp PDF, v.v.
  • Trích xuất URL của hình ảnh trên trang web.
    • Nếu số là tuần tự
    • Chiết xuất với Súp đẹp
  • Tải xuống hàng loạt nhiều hình ảnh từ danh sách URL

Tải xuống hình ảnh bằng cách chỉ định URL.

Bạn chỉ có thể sử dụng thư viện chuẩn để tải xuống các tệp riêng lẻ bằng cách chỉ định URL của chúng; không cần cài đặt bổ sung.

Mã ví dụ

Sau đây là ví dụ về chức năng tải xuống và lưu tệp bằng cách chỉ định URL và đường dẫn đích cũng như cách sử dụng của nó. Đoạn mã này hơi dài dòng vì mục đích giải thích. Một ví dụ đơn giản được đưa ra dưới đây.

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)

Để chỉ định thư mục đích và lưu tệp với tên tệp URL, hãy làm như sau

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)

Nó trích xuất tên tệp từ URL với os.path.basename () và kết hợp nó với thư mục được chỉ định với os.path.join () để tạo đường dẫn đích.

Các phần sau đây mô tả phần thu thập dữ liệu và phần lưu dữ liệu dưới dạng tệp.

urllib.request.urlopen():Mở URL

Sử dụng urllib.request.urlopen () để mở URL và truy xuất dữ liệu. Lưu ý rằng urllib.urlopen () đã không được chấp nhận trong Python 2.6 trở về trước. urllib.request.urlretrieve () vẫn chưa được chấp nhận, nhưng có thể sẽ có trong tương lai.

Để tránh dừng khi một ngoại lệ xảy ra, hãy bắt lỗi bằng cách thử và ngoại trừ.

Trong ví dụ, urllib.error được nhập và chỉ urllib.error.URLError được ghi lại một cách rõ ràng. Thông báo lỗi sẽ được hiển thị khi URL của tệp không tồn tại.

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

Nếu bạn cũng muốn bắt các ngoại lệ (FileNotFoundError, v.v.) khi lưu cục bộ, hãy làm như sau.
(urllib.error.URLError, FileNotFoundError)

Cũng có thể sử dụng Yêu cầu thư viện của bên thứ ba thay vì urllib thư viện tiêu chuẩn để mở url và lấy dữ liệu.

Ghi vào tệp ở chế độ nhị phân trong open ()

Dữ liệu có thể lấy được với urllib.request.urlopen () là một chuỗi byte (kiểu byte).

Mở () với mode = ‘wb’ khi đối số thứ hai ghi dữ liệu dưới dạng nhị phân. w có nghĩa là ghi và b có nghĩa là nhị phân.

Một ví dụ mã đơn giản hơn

Các câu lệnh lồng nhau có thể được viết cùng một lúc, được phân tách bằng dấu phẩy.

Sử dụng điều này, chúng ta có thể viết như sau.

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)

Tải xuống tệp ZIP, tệp PDF, v.v.

Các ví dụ cho đến nay là để tải xuống và lưu tệp hình ảnh, nhưng vì chúng ta chỉ mở tệp trên web và lưu dưới dạng tệp cục bộ, nên các chức năng tương tự có thể được sử dụng cho các loại tệp khác.

Bạn có thể tải xuống và lưu tệp bằng cách chỉ định 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)

Lưu ý rằng URL được chỉ định trong hàm này phải là một liên kết đến chính tệp.

Ví dụ: trong trường hợp tệp kho lưu trữ GitHub, URL sau có phần mở rộng là pdf nhưng thực chất là một trang html. Nếu URL này được chỉ định trong hàm trên, thì nguồn html sẽ được tải xuống.

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

Liên kết đến thực thể tệp là URL sau, bạn cần chỉ định nếu muốn tải xuống và lưu tệp.

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

Cũng có trường hợp quyền truy cập bị hạn chế bởi tác nhân người dùng, liên kết giới thiệu, v.v., khiến bạn không thể tải xuống. Chúng tôi không đảm bảo rằng tất cả các tệp sẽ được tải xuống.

Có thể dễ dàng sử dụng Yêu cầu để thay đổi hoặc thêm tiêu đề yêu cầu như tác nhân người dùng.

Trích xuất URL của hình ảnh trên trang web.

Để tải xuống tất cả các hình ảnh trong một trang cùng một lúc, trước tiên hãy trích xuất URL của các hình ảnh và tạo một danh sách.

Nếu số là tuần tự

Nếu URL của hình ảnh bạn muốn tải xuống là một số tuần tự đơn giản, thì thật dễ dàng. Nếu các URL không chỉ là số thứ tự mà còn có một số đều đặn, thì việc tạo danh sách URL theo các quy tắc sẽ dễ dàng hơn là cóp nhặt với Beautiful Soup (xem bên dưới).

Sử dụng ký hiệu đọc hiểu danh sách.

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

Trong ví dụ trên, {: 03} được sử dụng cho một số liên tiếp có 3 chữ số không điền; {} được sử dụng khi không cần điền số 0 và {: 05} được sử dụng cho số có 5 chữ số thay vì 3 chữ số. Để biết thêm thông tin về phương pháp định dạng của chuỗi str, hãy xem bài viết sau.

Ngoài ra, ở đây chúng tôi đang sử dụng pprint để làm cho đầu ra dễ đọc hơn.

Chiết xuất với Súp đẹp

Để trích xuất hàng loạt URL hình ảnh từ các trang web, hãy sử dụng Beautiful Soup.

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

from bs4 import BeautifulSoup

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

Trong ví dụ, URL của hình ảnh thu nhỏ của trang web này được trích xuất.

Cấu trúc khác nhau tùy thuộc vào trang web, nhưng về cơ bản nó được thu thập như sau.

  • Nhận danh sách & lt; img & gt; gắn thẻ các đối tượng bằng cách chỉ định lớp, id, v.v. của khối chứa nhiều hình ảnh bạn muốn tải xuống.
    • soup.find(class_='list').find_all('img')
  • Lấy URL của hình ảnh từ phần tử src hoặc phần tử data-src của & lt; img & gt; nhãn.
    • img.get('data-src')

Mã mẫu trên chỉ là một ví dụ và không đảm bảo hoạt động.

Tải xuống hàng loạt nhiều hình ảnh từ danh sách URL

Nếu bạn có danh sách các URL, bạn có thể chỉ cần chuyển nó trong một vòng lặp for và gọi hàm tải xuống và lưu tệp với URL đầu tiên được hiển thị. Vì danh sách URL tạm thời, hàm gọi download_image_dir () được nhận xét ở đây.

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

Để không làm quá tải máy chủ, tôi sử dụng time.sleep () để tạo thời gian chờ cho mỗi lần tải xuống hình ảnh. Đơn vị tính bằng giây, vì vậy trong ví dụ trên, mô-đun thời gian được nhập và sử dụng.

Ví dụ là đối với tệp hình ảnh, nhưng các loại tệp khác cũng có thể được tải xuống cùng nhau, miễn là chúng được liệt kê.

Copied title and URL