使用python将四万多图片分文件夹存储


1

前言

先说明下背景吧,之前学习Scrapy爬了一个网站的美女图片,爬完后发现数量居然有4W多个,此前完全没想到这么多,所以存储时直接放在了一个文件夹,导致现在打开文件夹时巨慢无比,因此想要批量给他们归个类,按不同的文件夹存储。

爬取图片时除了下载了图片外,还通过MySQL存储 了图片的相关信心,其中包括图片类型,如下图:

1590928383128

且图片存储的文件名,是使用img_name和image_urls经过处理后拼接而来,很遗憾数据库没有存储:

1590928776312

想要按照数据库中的img_type将图片文件分文件夹存储。

目前思路是:

  1. 更新数据库表,按爬虫存储图片的规则,生成文件名称放在images字段;
  2. 遍历文件夹,将文件名匹对images字段,匹配上后将文件移入img_type命名的子文件夹;

因为要操作存储图片信息的数据库,我想直接使用爬虫使用的model类,因此将脚本放在scrapy项目的根目录下了,和pipiline.py同级目录,使用到的model相关内容可以参考另一篇文章《Scrapy的pipelines使用sqlalchemy》,model相关内容如下:

#model包的__init__.py文件
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

#创建对象基类
Base = declarative_base()

#初始化数据库连接
engine = create_engine('mysql+pymysql://root:98256582@localhost:3306/get_ais?charset=utf8',pool_size=100)

#返回数据库会话
def loadSession():
    Session = sessionmaker(bind=engine)
    session = Session()
    return session
#model包下定义图片model的模块
from sqlalchemy import String,Column,DateTime,Text,Integer
from . import Base

class IMG(Base):
    __tablename__ = 'ais_img'

    img_xq_url = Column(String(100),nullable = True)
    img_name = Column(String(100),nullable = True)
    img_type = Column(String(20),nullable = True)
    img_pf = Column(String(10),nullable = True)
    img_createdate = Column(DateTime,nullable = True)
    image_urls = Column(String(100),primary_key = True,nullable = False)
    images  = Column(String(200),nullable = True)

更新数据库

确保脚本文件和model包在同一目录,否则要调整import的方法,脚本及解释如下:

#引入model包__init__.py里面获取数据库连接的函数
from model import loadSession
#引入model里面存储图片信息的模型类
from model.ais_img import IMG
#跟爬虫同样逻辑处理文件名,使用了正则表达式
import re
#由于处理含汉字的url转换的包和函数
from urllib.parse import unquote

#获取数据库连接
session = loadSession()
#查询出表里面所有的对象,每个对象是一个obj,相当于一行数据
ru_list = session.query(IMG).filter(1==1).all()
#一个个对象循环,拿出img_name和image_urls进行处理和拼接
for ru in ru_list:
    #使用obj.column方式,获取字段的值
    img_name = ru.img_name
    image_urls = ru.image_urls
    #用_拼接name和url里面除网址外的部分
    zh = img_name+'_'+unquote("".join(re.findall(".com/([\w\W]+)",image_urls)))
    #用正则替换掉不能作为文件名的特殊符号
    images=re.sub(r'[\/:*?"<>|]', '_',zh)
    #将拼接好的文件名更新到对象的images字段
    ru.images=images
    #提交更新
    session.commit()
    print(img_name,image_urls,images)

执行这个脚本,会一行行处理数据,4W多行大概花了4个小时,确实好慢;如果不是因为url的处理以及文件名特殊字符的处理在SQL里面太过麻烦,直接写SQL语句处理会快得多。

匹对移动图片

现在数据库已有文件的名字,那么我们可以开始遍历文件夹里面的文件,并按文件名在数据库查出图片类型,进而移动文件到图片类型命名的文件夹。

python操作文件主要使用os,shutil这两个自带的包,我们先写一个移动文件的函数:

import os,shutil
#移动文件参数为:文件目录、文件名称、文件全路径名称
def move_img(s_path,filename,data_fullname):
    #有些文件在数据库可能找不到对应的记录,为了避免超出list长度的错误中断程序执行,加一个异常捕获
    try:
        #获取数据库连接
        session=loadSession()
        #获取文件名对应的数据库obj,结果是一个list,因为有可能查到多行数据
        #filter还可以使用like模糊查询filter(IMG.images.like(filename+'%'))
        img_obj = session.query(IMG).filter(IMG.images==filename).all()
        #拼接文件目录和图片类型,形成新的文件目录,如果数据库有多个同名文件记录,则使用第一个
        type_dir = os.path.join(s_path,img_obj[0].img_type)
        print('新文件路径为:%s'%type_dir)
        #如果新路径不存在,则创建
        if not os.path.exists(type_dir):
            os.mkdir(type_dir)
        #shutil.move移动文件,第一个参数是文件全路径名称,第二个参数是路径时移动到该路径,是全路径名称时重命名并移动到该路径
        shutil.move(data_fullname,type_dir)
        #关闭数据库连接
        session.close()
    except Exception as e:
        print('错误信息%s'%e)

接下来循环图片所在目录,然后每个文件都对应执行上面这个函数即可:


#遍历文件夹获取文件名的函数
def get_filename(s_path):
    #遍历文件夹,获取文件夹下所有文件名和文件夹
    list=os.listdir(s_path)
    for data in list:
        #拼接目录和目录下的对象,形成全路径
        data_fullname=os.path.join(s_path,data)
        #isfile判断是否为文件,为文件则调用移动文件的函数
        if os.path.isfile(data_fullname):            
            print('文件为:%s'%data_fullname)
            print(data)
            move_img(s_path,data,data_fullname)

最后写一个文件入口判断,代入文件夹路径,调用get_filename()函数:

if __name__ == "__main__":
    get_filename(r'C:\06Python\Scrapy\get_ais\get_ais\filedata\img')

执行完成后,发现图片以及按需求分类存放了,还剩少数数据库没记录的,手工处理下即可。


文章作者: 无咎
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 无咎 !
评论
 上一篇
用Python词云库WordClound制作词云图片 用Python词云库WordClound制作词云图片
前言之前练习Scrapy爬取网页文本,爬完后发现有2W多个TXT文档,如果一个个去看内容的话肯定不现实,这时突然想起了快速了解文本信息的‘词云’,因此萌生了用这2W多TXT文档制作一个词云图片快速了解核心内容的想法,顺便熟悉一下Python
下一篇 
Scrapy的pipelines使用sqlalchemy Scrapy的pipelines使用sqlalchemy
前言Scrapy爬取到的数据可以使用MySql持久化存储,通常Scrapy通过在pipiline.py里面连接数据库获取游标,然后写原生SQL语句来插入数据到Mysql里面,所以一旦数据字段较多时,pipiline里面会出现大段SQL语句,
2020-05-30
  目录