AI摘要:该项目提供了一个图形界面程序,用于从视觉中国批量下载图片。用户可设置关键词、下载数量、下载模式(顺序、随机、跳跃)、统一命名及保存路径。程序使用Python的Tkinter库构建界面,requests和BeautifulSoup进行网页抓取和图片下载,并带有错误处理和日志记录功能。项目地址:[https://github.com/itmanmax/getvgcg-picture](https://github.com/itmanmax/getvgcg-picture) 仅供娱乐使用,禁止商用。

Powered by 返回门户.

批量爬取图片-视觉中国

2024年12月4日00:20:52带编写

使用教程

  1. 去github下载 https://github.com/itmanmax/getvgcg-picture
  2. 双击bat启动image
  3. 功能介绍:

    • 输入搜索的关键词
    • 下载图片数量
    • 爬取的方式
    • 是否统一命名 :格式为foods1.jpg foods2.jpg 这种
    • 以及保存位置

imageimageimage

使用如从简单!

声明:仅供娱乐使用,请勿商业使用!

源码介绍

代码分享

import os
import time
import requests
from bs4 import BeautifulSoup
import random
import tkinter as tk
from tkinter import ttk, messagebox
import logging
from datetime import datetime

class ImageDownloaderGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("图片下载器")
        self.root.geometry("600x650")
    
        # 设置整体样式
        style = ttk.Style()
        style.configure('TLabel', font=('微软雅黑', 10))
        style.configure('TButton', font=('微软雅黑', 10))
        style.configure('TRadiobutton', font=('微软雅黑', 10))
        style.configure('TCheckbutton', font=('微软雅黑', 10))
    
        # 创建主框架
        main_frame = ttk.Frame(root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
    
        # 搜索关键词区域
        search_frame = ttk.LabelFrame(main_frame, text="搜索设置", padding="10")
        search_frame.pack(fill=tk.X, pady=10)
    
        ttk.Label(search_frame, text="搜索关键词:").pack(anchor='w')
        self.search_entry = ttk.Entry(search_frame, width=40)
        self.search_entry.pack(fill=tk.X, pady=(5, 10))
        self.search_entry.insert(0, "Restaurant")
    
        ttk.Label(search_frame, text="下载数量:").pack(anchor='w')
        self.count_entry = ttk.Entry(search_frame, width=40)
        self.count_entry.pack(fill=tk.X, pady=5)
        self.count_entry.insert(0, "10")
    
        # 下载模式区域
        mode_frame = ttk.LabelFrame(main_frame, text="下载模式", padding="10")
        mode_frame.pack(fill=tk.X, pady=10)
    
        self.download_mode = tk.StringVar(value="顺序")
        ttk.Radiobutton(mode_frame, text="顺序下载", variable=self.download_mode, value="顺序").pack(anchor='w', pady=2)
        ttk.Radiobutton(mode_frame, text="随机下载", variable=self.download_mode, value="随机").pack(anchor='w', pady=2)
        ttk.Radiobutton(mode_frame, text="跳跃下载", variable=self.download_mode, value="跳跃").pack(anchor='w', pady=2)
    
        # 跳跃设置区域
        jump_frame = ttk.Frame(mode_frame)
        jump_frame.pack(fill=tk.X, pady=(5, 0))
        ttk.Label(jump_frame, text="跳跃距离:").pack(side='left')
        self.jump_entry = ttk.Entry(jump_frame, width=10)
        self.jump_entry.pack(side='left', padx=5)
        self.jump_entry.insert(0, "2")
    
        # 命名选项区域
        name_frame = ttk.LabelFrame(main_frame, text="命名选项", padding="10")
        name_frame.pack(fill=tk.X, pady=10)
    
        self.rename_var = tk.BooleanVar(value=False)
        self.rename_check = ttk.Checkbutton(
            name_frame,
            text="统一命名(例:关键词1.jpg, 关键词2.jpg)",
            variable=self.rename_var
        )
        self.rename_check.pack(anchor='w')
    
        # 保存路径区域
        path_frame = ttk.LabelFrame(main_frame, text="保存位置", padding="10")
        path_frame.pack(fill=tk.X, pady=10)
    
        path_input_frame = ttk.Frame(path_frame)
        path_input_frame.pack(fill=tk.X)
    
        self.path_entry = ttk.Entry(path_input_frame)
        self.path_entry.pack(side='left', fill=tk.X, expand=True, padx=(0, 5))
        self.path_entry.insert(0, r'C:\Users\86147\图片\pypicture')
    
        self.browse_btn = ttk.Button(path_input_frame, text="浏览", command=self.browse_path)
        self.browse_btn.pack(side='right')
    
        # 下载按钮区域
        btn_frame = ttk.Frame(main_frame)
        btn_frame.pack(fill=tk.X, pady=20)
    
        download_btn = ttk.Button(btn_frame, text="开始下载", command=self.start_download, style='Accent.TButton')
        download_btn.pack(pady=5)
    
        # 进度显示
        self.progress_label = ttk.Label(main_frame, text="", font=('微软雅黑', 9))
        self.progress_label.pack(pady=10)
    
        # 添加状态栏
        self.status_label = ttk.Label(root, text="就绪", relief=tk.SUNKEN, anchor='w')
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
    
        # 设置日志
        self.setup_logging()

    def setup_logging(self):
        # 配置日志
        self.logger = logging.getLogger('ImageDownloader')
        self.logger.setLevel(logging.INFO)
    
        # 创建文件处理器
        fh = logging.FileHandler('error.txt', encoding='utf-8')
        fh.setLevel(logging.ERROR)
    
        # 设置日志格式
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
    
        self.logger.addHandler(fh)

    def browse_path(self):
        from tkinter import filedialog
        path = filedialog.askdirectory()
        if path:
            self.path_entry.delete(0, tk.END)
            self.path_entry.insert(0, path)

    def start_download(self):
        self.status_label.config(text="正在下载...")
        keyword = self.search_entry.get().strip()
        save_path = self.path_entry.get().strip()
    
        try:
            count = int(self.count_entry.get().strip())
        except ValueError:
            messagebox.showerror("错误", "请输入有效的下载数量!")
            return
        
        if not keyword:
            messagebox.showerror("错误", "请输入搜索关键词!")
            return
        
        if not save_path:
            messagebox.showerror("错误", "请选择保存路径!")
            return
        
        # 创建以关键词命名的子文件夹
        keyword_folder = os.path.join(save_path, keyword)
        if not os.path.exists(keyword_folder):
            os.makedirs(keyword_folder)
        
        self.progress_label.config(text="开始下载...")
        self.root.update()
    
        try:
            self.download_images(keyword, count, keyword_folder)
            messagebox.showinfo("完成", f"成功下载了 {count} 张图片到文件夹 {keyword_folder}!")
            self.status_label.config(text="下载完成")
        except Exception as e:
            messagebox.showerror("错误", f"下载过程中出现错误:{str(e)}")
            self.status_label.config(text="下载出错")
        finally:
            self.progress_label.config(text="")

    def download_images(self, keyword, count, save_folder):
        try:
            base_url = f'https://www.vcg.com/creative-image/{keyword}'
        
            # 更新状态
            self.progress_label.config(text="正在获取图片列表...")
            self.root.update()
        
            soup = make_soup(base_url)
            all_img_urls = get_image_urls(soup)
        
            if not all_img_urls:
                raise Exception("未找到任何图片")
        
            # 根据下载模式选择图片
            if self.download_mode.get() == "顺序":
                img_urls = all_img_urls[:count]
            elif self.download_mode.get() == "随机":
                img_urls = random.sample(all_img_urls, min(count, len(all_img_urls)))
            elif self.download_mode.get() == "跳跃":
                try:
                    jump_distance = int(self.jump_entry.get().strip())
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的跳跃距离!")
                    return
                img_urls = all_img_urls[::jump_distance][:count]
        
            # 确定起始编号
            start_index = self.get_start_index(keyword, save_folder)
        
            # 创建进度条
            progress_window = tk.Toplevel(self.root)
            progress_window.title("下载进度")
            progress_window.geometry("300x150")
            progress_window.transient(self.root)  # 设置为主窗口的子窗口
        
            ttk.Label(progress_window, text="正在下载...").pack(pady=10)
            progress_bar = ttk.Progressbar(progress_window, length=200, mode='determinate')
            progress_bar.pack(pady=10)
            progress_text = ttk.Label(progress_window, text="")
            progress_text.pack(pady=10)
        
            # 设置进度条最大值
            progress_bar['maximum'] = len(img_urls)
        
            for i, img_url in enumerate(img_urls, start=1):
                # 更新进度显示
                progress_text.config(text=f"正在下载第 {i}/{len(img_urls)} 张图片")
                progress_bar['value'] = i
                self.status_label.config(text=f"正在下载: {i}/{len(img_urls)}")
            
                # 更新界面
                progress_window.update()
                self.root.update_idletasks()
            
                if self.rename_var.get():
                    filename = f"{keyword}{start_index + i - 1}.jpg"
                else:
                    filename = img_url.split('/')[-1].split('?')[0]
                
                save_path = os.path.join(save_folder, filename)
            
                try:
                    download_image(img_url, save_path)
                except Exception as e:
                    self.logger.error(f"下载失败 {img_url}: {str(e)}")
                    continue
            
                # 控制更新频率,避免界面卡顿
                if i % 2 == 0:  # 每下载两张图片更新一次界面
                    time.sleep(0.1)  # 短暂延时,让界面有机会响应
        
            # 关闭进度窗口
            progress_window.destroy()
        
        except Exception as e:
            self.logger.error(f"下载过程出错: {str(e)}")
            raise

    def get_start_index(self, keyword, save_folder):
        # 获取文件夹中已有的最大编号
        existing_files = [f for f in os.listdir(save_folder) if f.startswith(keyword) and f.endswith('.jpg')]
        max_index = 0
        for file in existing_files:
            try:
                index = int(file[len(keyword):-4])  # 提取编号
                if index > max_index:
                    max_index = index
            except ValueError:
                continue
        return max_index + 1

def make_soup(url):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36'
        }
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        return BeautifulSoup(response.text, 'html.parser')
    except Exception as e:
        logging.error(f'Error making soup for {url}: {str(e)}')
        raise

def get_image_urls(soup):
    img_urls = []
    for img_tag in soup.find_all('img'):
        img_url = img_tag.get('data-src') or img_tag.get('src')
        if img_url:
            if not img_url.lower().endswith('.jpg') and not img_url.lower().endswith('.jpeg'):
                continue
            
            if img_url.startswith('//'):
                img_url = 'https:' + img_url
            elif img_url.startswith('/'):
                img_url = 'https://www.vcg.com' + img_url
        
            logging.debug(f'Found image URL: {img_url}')
            img_urls.append(img_url)
    return img_urls

def download_image(url, save_path):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36'
        }
        with requests.get(url, headers=headers, stream=True) as response:
            response.raise_for_status()
            with open(save_path, 'wb') as file:
                for chunk in response.iter_content(chunk_size=8192):
                    if chunk:
                        file.write(chunk)
        return True
    except Exception as e:
        logging.error(f'Error downloading {url}: {str(e)}')
        return False

def main():
    root = tk.Tk()
    app = ImageDownloaderGUI(root)
    root.mainloop()

if __name__ == '__main__':
    main()

图片下载器 GUI 详解

1. 项目概述

本项目实现了一个简单的图片下载器 GUI,用户可以通过输入关键词和下载模式来下载对应的图片。以下是程序的主要功能与实现细节。

2. 界面搭建

此部分代码负责创建一个基本的图形用户界面,允许用户输入搜索关键词、下载数量和选择下载模式。

class ImageDownloaderGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("图片下载器")
        self.root.geometry("600x650")
    
        # 设置整体样式
        style = ttk.Style()
        style.configure('TLabel', font=('微软雅黑', 10))
        style.configure('TButton', font=('微软雅黑', 10))
        style.configure('TRadiobutton', font=('微软雅黑', 10))
        style.configure('TCheckbutton', font=('微软雅黑', 10))
    
        # 创建主框架
        main_frame = ttk.Frame(root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
    
        # 搜索关键词区域
        search_frame = ttk.LabelFrame(main_frame, text="搜索设置", padding="10")
        search_frame.pack(fill=tk.X, pady=10)
    
        ttk.Label(search_frame, text="搜索关键词:").pack(anchor='w')
        self.search_entry = ttk.Entry(search_frame, width=40)
        self.search_entry.pack(fill=tk.X, pady=(5, 10))
        self.search_entry.insert(0, "Restaurant")
  
        ttk.Label(search_frame, text="下载数量:").pack(anchor='w')
        self.count_entry = ttk.Entry(search_frame, width=40)
        self.count_entry.pack(fill=tk.X, pady=5)
        self.count_entry.insert(0, "10")

3. 功能实现

下面的代码展示了如何实现图片的下载逻辑,包括选择下载模式、下载进度的显示,以及日志记录等功能。

def start_download(self):
    self.status_label.config(text="正在下载...")
    keyword = self.search_entry.get().strip()
    save_path = self.path_entry.get().strip()

    try:
        count = int(self.count_entry.get().strip())
    except ValueError:
        messagebox.showerror("错误", "请输入有效的下载数量!")
        return

    if not keyword:
        messagebox.showerror("错误", "请输入搜索关键词!")
        return
  
    if not save_path:
        messagebox.showerror("错误", "请选择保存路径!")
        return

    # 创建以关键词命名的子文件夹
    keyword_folder = os.path.join(save_path, keyword)
    if not os.path.exists(keyword_folder):
        os.makedirs(keyword_folder)

    self.progress_label.config(text="开始下载...")
    self.root.update()
  
    try:
        self.download_images(keyword, count, keyword_folder)
        messagebox.showinfo("完成", f"成功下载了 {count} 张图片到文件夹 {keyword_folder}!")
        self.status_label.config(text="下载完成")
    except Exception as e:
        messagebox.showerror("错误", f"下载过程中出现错误:{str(e)}")
        self.status_label.config(text="下载出错")
    finally:
        self.progress_label.config(text="")

4. 图片下载逻辑

在下载图片时,需要获取图片链接并根据用户选择的模式进行下载,当前代码在错误处理方面还有待改进。

def download_images(self, keyword, count, save_folder):
    try:
        base_url = f'https://www.vcg.com/creative-image/{keyword}'
        soup = make_soup(base_url)
        all_img_urls = get_image_urls(soup)

        if not all_img_urls:
            raise Exception("未找到任何图片")
    
        # 根据下载模式选择图片
        if self.download_mode.get() == "顺序":
            img_urls = all_img_urls[:count]
        elif self.download_mode.get() == "随机":
            img_urls = random.sample(all_img_urls, min(count, len(all_img_urls)))
        elif self.download_mode.get() == "跳跃":
            jump_distance = int(self.jump_entry.get().strip()) if self.jump_entry.get() else 2
            img_urls = all_img_urls[::jump_distance][:count]
    
        # 下载图片并更新进度
        for i, img_url in enumerate(img_urls, 1):
            # 下载逻辑
            pass

5. 获取与下载图片

使用 requests​ 库和 BeautifulSoup​ 解析 HTML 页面,获得图片 URL 并进行下载。同时通过日志记录下载状态。

def make_soup(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return BeautifulSoup(response.text, 'html.parser')

def download_image(url, save_path):
    with requests.get(url, stream=True) as response:
        response.raise_for_status()
        with open(save_path, 'wb') as file:
            for chunk in response.iter_content(chunk_size=8192):
                file.write(chunk)

总结

本项目的图片下载器为用户提供了一个简洁的界面,以方便地下载指定关键词的图片。通过完善的错误处理和日志记录功能,增强了系统的稳定性和用户体验。未来可以考虑添加更多图片来源,提升下载速度,以及优化界面的响应能力。

摘要

本项目实现了一个简单的图片下载器 GUI,用户可以根据关键词下载指定数量的图片。以下是使用与功能的概述:

使用教程

  1. 从 GitHub 下载项目:getvgcg-picture
  2. 双击启动 bat 文件以打开程序。
  3. 用户可以设置搜索关键词、下载数量、下载方式(顺序、随机或跳跃)、统一命名选项以及保存路径。

功能介绍

  • 支持输入关键词和下载数量。
  • 可选择下载模式,包括顺序、随机和跳跃下载。
  • 提供统一命名的选项(如 foods1.jpg)。
  • 可自定义保存位置。

声明:该工具仅供娱乐使用,请勿用于商业目的。

源码简介

代码使用 Python 和 Tkinter 库构建 GUI,通过 requests​ 和 BeautifulSoup​ 库实现网页抓取与图片下载。程序包括状态记录及错误处理,确保用户在下载过程中获得及时信息和反馈。

  • 界面:用户友好的输入框和按钮。
  • 下载逻辑:根据用户设置选择图片并进行下载,同时展示下载进度。

整体而言,本图片下载器提供了一种简便的方式来获取网络图片,适合对图库有需求的用户。未来可加入更多功能,如支持不同图片格式、提高下载速度等。

本文章提取的链接:

最后修改:2024 年 12 月 04 日
如果觉得我的文章挺有趣,赞赏一杯小奶茶
END
本文作者:
文章标题:批量爬取图片-视觉中国
本文地址:https://www.maxtral.fun/index.php/archives/194/
版权说明:若无注明,本文皆MAXBROSER原创,转载请保留文章出处。