Mag-download ng mga larawan at iba pang mga file mula sa web sa Python (indibidwal o sa mga batch)

Negosyo

Ipinapaliwanag ng sumusunod kung paano tukuyin ang URL ng isang imahe, ZIP, PDF, o iba pang file sa Web sa Python, i-download ito, at i-save ito bilang isang lokal na file.

  • Mag-download ng mga larawan sa pamamagitan ng pagtukoy sa URL.
    • Halimbawa ng code
    • urllib.request.urlopen():Buksan ang URL
    • open():Sumulat sa isang file sa binary mode
    • Isang mas simpleng halimbawa ng code
  • Mag-download ng mga ZIP file, PDF file, atbp.
  • I-extract ang URL ng larawan sa web page.
    • Kung ang numero ay sequential
    • Extract na may Magagandang Sopas
  • Batch na mag-download ng maraming larawan mula sa isang listahan ng mga URL

Mag-download ng mga larawan sa pamamagitan ng pagtukoy sa URL.

Magagamit mo lang ang karaniwang library upang mag-download ng mga indibidwal na file sa pamamagitan ng pagtukoy sa kanilang mga URL; walang karagdagang pag-install ang kinakailangan.

Halimbawa ng code

Ang sumusunod ay isang halimbawa ng isang function na nagda-download at nagse-save ng file sa pamamagitan ng pagtukoy sa URL at patutunguhang path, at sa paggamit nito. Medyo verbose ang code na ito para sa paliwanag. Ang isang simpleng halimbawa ay ibinigay sa ibaba.

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)

Upang tukuyin ang patutunguhang direktoryo at i-save ang file na may URL file name, gawin ang sumusunod

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)

Kinukuha nito ang pangalan ng file mula sa URL na may os.path.basename() at isinasama ito sa direktoryo na tinukoy sa os.path.join() upang buuin ang patutunguhang landas.

Inilalarawan ng mga sumusunod na seksyon ang bahagi ng pagkuha ng data at ang bahagi ng pag-save ng data bilang isang file.

urllib.request.urlopen():Buksan ang URL

Gamitin ang urllib.request.urlopen() upang buksan ang URL at kunin ang data. Tandaan na ang urllib.urlopen() ay hindi na ginagamit sa Python 2.6 at mas maaga. Ang urllib.request.urlretrieve() ay hindi pa tinatanggal, ngunit maaaring nasa hinaharap.

Upang maiwasan ang paghinto kapag may nangyaring exception, hulihin ang error gamit ang try and except.

Sa halimbawa, ang urllib.error ay na-import at tanging ang urllib.error.URLError ang tahasang nakunan. Ang mensahe ng error ay ipapakita kapag ang URL ng file ay hindi umiiral.

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

Kung gusto mo ring makakuha ng mga exception (FileNotFoundError, atbp.) kapag nagse-save nang lokal, gawin ang sumusunod.
(urllib.error.URLError, FileNotFoundError)

Posible ring gamitin ang Mga Kahilingan sa library ng third-party sa halip na ang karaniwang urllib ng library upang buksan ang url at makuha ang data.

Sumulat sa isang file sa binary mode sa open()

Ang data na maaaring makuha gamit ang urllib.request.urlopen() ay isang byte string (uri ng bytes).

Open() na may mode=’wb’ habang isinusulat ng pangalawang argumento ang data bilang binary. Ang ibig sabihin ng w ay isulat at ang ibig sabihin ng b ay binary.

Isang mas simpleng halimbawa ng code

Maaaring isulat nang sabay-sabay ang mga nested na may mga pahayag, na pinaghihiwalay ng mga kuwit.

Gamit ito, maaari nating isulat ang sumusunod.

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)

Mag-download ng mga ZIP file, PDF file, atbp.

Ang mga halimbawa sa ngayon ay para sa pag-download at pag-save ng mga file ng imahe, ngunit dahil binubuksan lang namin ang isang file sa web at sine-save ito bilang isang lokal na file, ang parehong mga function ay maaaring gamitin para sa iba pang mga uri ng mga file.

Maaari kang mag-download at mag-save ng mga file sa pamamagitan ng pagtukoy sa 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)

Tandaan na ang URL na tinukoy sa function na ito ay dapat na isang link sa mismong file.

Halimbawa, sa kaso ng GitHub repository file, ang sumusunod na URL ay may extension na pdf ngunit talagang isang html page. Kung ang URL na ito ay tinukoy sa function sa itaas, ang html source ay mada-download.

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

Ang link sa file entity ay ang sumusunod na URL, na kailangan mong tukuyin kung gusto mong i-download at i-save ang file.

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

Mayroon ding mga kaso kung saan ang pag-access ay pinaghihigpitan ng user agent, referrer, atbp., na ginagawang imposibleng i-download. Hindi namin ginagarantiya na ang lahat ng mga file ay mada-download.

Madaling gamitin ang Mga Kahilingan upang baguhin o magdagdag ng mga header ng kahilingan gaya ng user agent.

I-extract ang URL ng larawan sa web page.

Upang i-download ang lahat ng mga larawan sa isang pahina nang sabay-sabay, i-extract muna ang mga URL ng mga larawan at lumikha ng isang listahan.

Kung ang numero ay sequential

Kung ang URL ng larawang gusto mong i-download ay isang simpleng sequential number, madali lang ito. Kung ang mga URL ay hindi lamang magkakasunod na mga numero ngunit mayroon ding ilang regularidad, mas madaling gumawa ng listahan ng mga URL ayon sa mga panuntunan sa halip na mag-scrap gamit ang Beautiful Soup (tingnan sa ibaba).

Gumamit ng notasyon sa pag-unawa sa listahan.

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

Sa halimbawa sa itaas, ang {:03} ay ginagamit para sa isang 3-digit na zero-filled na sequential number; Ginagamit ang {} kapag hindi kailangan ang zero-filling, at ang {:05} ay ginagamit para sa isang 5-digit na numero sa halip na 3 digit. Para sa karagdagang impormasyon tungkol sa paraan ng pag-format ng string str, tingnan ang sumusunod na artikulo.

Gayundin, dito kami ay gumagamit ng pprint upang gawing mas madaling basahin ang output.

Extract na may Magagandang Sopas

Upang kunin ang mga URL ng larawan mula sa mga web page nang maramihan, gamitin ang Beautiful Soup.

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

from bs4 import BeautifulSoup

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

Sa halimbawa, ang URL ng thumbnail na larawan ng website na ito ay kinuha.

Ang istraktura ay nag-iiba depende sa web page, ngunit karaniwang ito ay nakuha bilang mga sumusunod.

  • Kumuha ng listahan ng <img> i-tag ang mga bagay sa pamamagitan ng pagtukoy sa klase, id, atbp. ng bloke na naglalaman ng maraming larawang gusto mong i-download.
    • soup.find(class_='list').find_all('img')
  • Kunin ang URL ng larawan mula sa src element o data-src element ng <img> tag.
    • img.get('data-src')

Ang sample code sa itaas ay isang halimbawa lamang at hindi garantisadong gagana.

Batch na mag-download ng maraming larawan mula sa isang listahan ng mga URL

Kung mayroon kang listahan ng mga URL, maaari mo lang itong i-on sa isang for loop at tawagan ang function upang i-download at i-save ang file na may unang URL na ipinapakita. Dahil sa pansamantalang listahan ng URL, ang function call download_image_dir() ay nagkomento dito.

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

Upang hindi ma-overload ang server, gumagamit ako ng time.sleep() upang lumikha ng oras ng paghihintay para sa bawat pag-download ng larawan. Ang unit ay nasa segundo, kaya sa halimbawa sa itaas, ang time module ay na-import at ginagamit.

Ang halimbawa ay para sa mga file ng imahe, ngunit ang iba pang mga uri ng mga file ay maaaring ma-download nang magkasama, hangga’t nakalista ang mga ito.

Copied title and URL