ข้อมูลต่อไปนี้จะอธิบายวิธีระบุ URL ของรูปภาพ, ZIP, PDF หรือไฟล์อื่นๆ บนเว็บใน Python ดาวน์โหลดและบันทึกเป็นไฟล์ในเครื่อง
- ดาวน์โหลดภาพโดยระบุ URL
- ตัวอย่างโค้ด
urllib.request.urlopen()
:เปิด URLopen()
:เขียนไปยังไฟล์ในโหมดไบนารี- ตัวอย่างโค้ดที่ง่ายกว่า
- ดาวน์โหลดไฟล์ 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() ยังไม่เลิกใช้ แต่อาจเป็นในอนาคต
เพื่อหลีกเลี่ยงการหยุดเมื่อมีข้อยกเว้น ให้ตรวจจับข้อผิดพลาดด้วยการลองและยกเว้น
ในตัวอย่าง 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)
นอกจากนี้ยังสามารถใช้คำขอห้องสมุดบุคคลที่สามแทน 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 (ดูด้านล่าง)
ใช้สัญกรณ์ความเข้าใจรายการ
- บทความที่เกี่ยวข้อง:การใช้สัญกรณ์ความเข้าใจรายการ Python
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 ดูบทความต่อไปนี้
- บทความที่เกี่ยวข้อง:การแปลงรูปแบบใน Python, รูปแบบ (การเติมศูนย์, เลขชี้กำลัง, เลขฐานสิบหก, ฯลฯ )
นอกจากนี้ เรายังใช้ pprint เพื่อให้อ่านผลลัพธ์ได้ง่ายขึ้น
สกัดด้วยซุปที่สวยงาม
หากต้องการแยก URL รูปภาพออกจากหน้าเว็บจำนวนมาก ให้ใช้ Beautiful Soup
import os import time import urllib.error import urllib.request from bs4 import BeautifulSoup url = 'https://th.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 loop และเรียกใช้ฟังก์ชันเพื่อดาวน์โหลดและบันทึกไฟล์โดยแสดง 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() เพื่อสร้างเวลารอสำหรับการดาวน์โหลดแต่ละภาพ หน่วยเป็นวินาที ดังนั้นในตัวอย่างข้างต้น โมดูลเวลาจะถูกนำเข้าและใช้งาน
ตัวอย่างคือไฟล์รูปภาพ แต่ไฟล์ประเภทอื่นสามารถดาวน์โหลดพร้อมกันได้เช่นกัน ตราบใดที่อยู่ในรายการ