使用Python按文件名所包含的特定关键词实现文档分类整理

碎碎念

我作为中国最早接触互联网的一撮人,硬盘上有无数上古时代的图片,也有很多是从早已不怎么流行的论坛里下载的图片。
众所周知,这用PHPWind v7.5 搭建的,广泛使用的中文论坛,它的用户id其实都是对应着一串数字,发表的图片都是以论坛的文章版块分类来命名相应的格式,很有规律。
但是如何根据已经有的id来分门别类整理新下载的图片,这是一个难点。
我以往都是手动一个个的分类,查找,移动,复制,粘贴,效率很低,很容易出错。所以最早学Python的动力其实不是为了写爬虫,而是为了把我手动下载下来的海量的图片按照发帖人的id来分类归档。
比如我这里已经有id为jw11的家伙,他发的所有帖子的文件名都是像如下的格式一般:

82_25158_03405c1ea40bbd4.jpg
82_25158_03448e17837f098.jpg
82_25158_03806c963523233.jpg
82_25158_0392c5a9be503f8.jpg
82_25158_053b6be42c4002c.jpg
82_25158_059c497f183e2c1.jpg
82_25158_063d1c887f2b3f8.jpg
82_25158_0648bdd9358a3a1.jpg

那我已经知道了这个25158就是jw11,同理,我下载的一堆图片有各种各样的id,对应了各种各样的发帖人的id。
在学会Python以前,我的做法是新建一个叫做jw11的文件夹,然后手动在下载的目标文件夹里面搜索25158这个关键词,然后全选,选择剪切,再切换到jw11的文件夹里面去选择粘贴,如此往复,效率十分低下。

计算机的存在就是为了帮我们从重复的劳动中解脱出来,那么问题来了:

怎样把文件通过Python来处理,依据文件的文件名中含有的这一段标示为id的数字来对应文件夹的自动文件分类呢?

很可惜,虽然CSDN也好,简书也好,知乎也好,有铺天盖地数不清的文章教你玩转Python,教你进阶,教你入门,教你这教你那,偏偏我的需求就是在这世界上显得如此的特别,地球上偏没有人来教我该如何做。

我能怎么做,只好从零开始入门,一点点学,然后自己一点点总结做实验,在数不清的失败之后,终于有一天,它成功了!
而且速度奇快,以至于按下回车之后,我都不敢相信它真的实现了我的想法。
在这里写下来,造福有缘看到本文的各位:


正文

首先,上代码

import os
import shutil

'''
把新下载的文件夹放在id文件夹,确保里面至少有一张照片
把其余所有待分类的照片放在img文件夹

执行文档,将自动移动所有照片到相应的作者文件夹中
'''
folder_id = r'D:\TRY\id'
folder_img = r'D:\TRY\img'

id_raw = list(os.walk(folder_id))
id_files = id_raw[1:]

auid = dict()

for n in id_files:
    author = n[0]
    aid = n[2][0][3:9]
    auid.update({aid: author})

img_files = os.listdir(folder_img)
for i in img_files:
    if i[3:9] in auid.keys():
        orin = os.path.join(folder_img, i)
        dest = os.path.join(auid[i[3:9]], i)
        shutil.move(orin, dest)


解析代码

对于不求甚解,拿来就用的朋友,把上述代码拷贝走就可以关闭本文了,我也不在乎什么版权,也不在乎你们的赞还是不赞,但是只有一种情况我不能忍:
那就是你标明了出处,说这段代码这篇文章是我写的,可是你又拿去改的面目全非,这里少一点那里少一点,以至于别的朋友用不了,理解不能,到头来以为我水平不高,这个是不行的,我们是要脸的,切记。

首先

import os
import shutil

为了让Python能够实现文件的移动,对文件夹进行操作,需要引入两个库,os和shutil,这两个都是Python自带的标准库,所以也不需要你再另行安装,直接import就完事了。


接下来需要声明

folder_id = r'D:\TRY\id'
folder_img = r'D:\TRY\img'

你的文件从哪来,去哪里。
这里指定的两个文件夹,一个叫做id,一个叫做img。

id是包含了作者的id名的文件夹,比如jw11的文件夹就在这个id文件夹内。
此外,为了给程序一个参照,让它知道jw11就是25158,需要在jw11的文件夹内放至少一张属于它的图片,也就是任何一张类似82_25158_03405c1ea40bbd4.jpg的图片,只要是含有25158的都可以。

img文件夹就简单多了,把所有类似格式的图片都扔在里面,执行完程序之后,凡是能找到对应id的图片都会从这个文件夹中被剪切走,留下来的就是需要你再留意的了。
一般只要前期工作做到位,这个文件夹在执行完程序之后都是空的。

这里在引号前放一个r是因为我懒得写两个斜杠,放一个r的话就可以让python忽略引号内的斜杠,不然就要用转义字符\来把\转义成\,显得很不美观也不直观。


id_raw = list(os.walk(folder_id))
id_files = id_raw[1:]

这一段的目的是用os.walk()函数来遍历id和img目录,生成文件名列表
后面的切片操作[1:]也是为了留下作者的id,也就是文件夹的名称,而把后面跟着的文件夹里面的文件名剔除掉。

比如直接遍历,得到的id_raw如果用print函数打印出来会是下面的这样的东西

[('D:\\TRY\\id', ['jw11', 'coshi', 'liuxiao', 'qqqsssiw', '江小', '狼雪', '百合', '知一叶', '象人拍', '铁曼'], []), ('D:\\TRY\\id\\jw11', [], ['88_25158_e7755e644d79483.jpg']), ('D:\\TRY\\id\\coshi', [], ['88_293501_3d3ebf722eb7943.jpg']), ('D:\\TRY\\id\\liuxiao', [], ['88_278271_a114aedde9cf86a.png']), ('D:\\TRY\\id\\qqqsssiw', [], ['88_130878_6894267b8ac7571.jpg']),('D:\\TRY\\id\\江小', [], ['88_226990_c882fbb9f4e62a4.jpg']), ('D:\\\TRY\\id\\狼雪', [], ['88_246203_c07bb391177f4d3.jpg']), ('D:\\\TRY\\id\\百合', [], ['88_65202_d9fa5aad0397e5f.jpg']), ('D:\\\TRY\\id\\知一叶', [], ['88_217146_4e4e62e48f19b09.jpg']), ('D:\\\TRY\\id\\象人拍', [], ['88_293734_ebc4a29a509bdc2.jpg']), ('D:\\\TRY\\id\\铁曼', [], ['88_16661_237b863406986e0.jpg'])]

对于刚接触python的朋友来说,这是什么鬼,但是朋友们啊,这就是一个包含了我们想要的作者的id与它应该对应的文件名的列表啊!
接下来,让我们用切片操作id_files = id_raw[1:]把它分离一下看看:

[('D:\\TRY\\id\\jw11', [], ['88_25158_e7755e644d79483.jpg']), ('D:\\TRY\\id\\coshi', [], ['88_293501_3d3ebf722eb7943.jpg']), ('D:\\TRY\\id\\liuxiao', [], ['88_278271_a114aedde9cf86a.png']), ('D:\\TRY\\id\\qqqsssiw', [], ['88_130878_6894267b8ac7571.jpg']),('D:\\TRY\\id\\江小', [], ['88_226990_c882fbb9f4e62a4.jpg']), ('D:\\\TRY\\id\\狼雪', [], ['88_246203_c07bb391177f4d3.jpg']), ('D:\\\TRY\\id\\百合', [], ['88_65202_d9fa5aad0397e5f.jpg']), ('D:\\\TRY\\id\\知一叶', [], ['88_217146_4e4e62e48f19b09.jpg']), ('D:\\\TRY\\id\\象人拍', [], ['88_293734_ebc4a29a509bdc2.jpg']), ('D:\\\TRY\\id\\铁曼', [], ['88_16661_237b863406986e0.jpg'])]

仔细看,使劲看,看出什么名堂没有呢?对,列表中的第一项,也就是那个包含了所有文件夹名的那一项('D:\\TRY\\id', ['jw11', 'coshi', 'liuxiao', 'qqqsssiw', '江小', '狼雪', '百合', '知一叶', '象人拍', '铁曼'], [])被我们舍弃了,这就是切片的意义。


img_files = os.listdir(folder_img)

os.listdir()函数就简单多了,得到的全是该文件夹内的文件名的列表,类似于:

['82_25158_fe2f6e2c96aef1a.jpg', '82_25158_fe56c4415872950.jpg', '82_25158_fe5aac922ec1be2.jpg', '82_25158_febe6e5b82780e0.jpg', '82_25158_fec8f31d64ae59c.jpg', '82_25158_fee0c5cf16ceaa1.jpg', '82_25158_ff27a5397954489.jpg', '82_25158_ff2e52901689b3b.jpg', '82_25158_ff51fe758e511e8.jpg', '82_25158_ff58bb59e08aac0.jpg', '82_25158_ff7d27b587d5a2f.jpg', '82_25158_fff81d10d18eff9.jpg']

有了这两个表,我们就可以用python的dict()函数配合循环来构造字典了。
先构造一个空字典:

auid = dict()

for n in id_files:
    author = n[0]
    aid = n[2][0][3:9]
    auid.update({aid: author})

这里的author就是文件夹的路径,格式是这样的:

D:\TRY\id\jw11
D:\TRY\id\coshi
D:\TRY\id\liuxiao
D:\TRY\id\qqqsssiw
D:\TRY\id\江小
D:\TRY\id\狼雪

aid是通过对应的列表进行切片操作,得到的格式是这样的:

246203
65202_
254624
217146
293734
16661_

至于为什么是切[3:9],那是因为你数一下原文件名
82_25158_fff81d10d18eff9.jpg
0123456789012345678901234567

下面这一行是我做的记数,可见,从0开始,到27结束,一共28个字符。
Python中[3:9]的意思是从第三个字符串开始,也就是2开始,到第9个字符串为止。注意,这里的为止是指并不包括第9个字符,也就是说,其实是到第8个字符和第九个字符之间结束。
那么3到9实际上截出来的是345678这六个字符,也就是id所对应的数字25158_

有小伙伴说为啥你要连_一起截,那是因为有的老用户的id是5位的,比如这位jw11,他就是五位数的id,新一点的朋友是六位数的,如果不多截一位,就会产生错误。

解释完这一段,我们继续看循环构造出来的字典:

auid.update({aid: author})

因为上面已经构造过了一个空字典,这里用.update 函数来填充字典,这样字典就会从空字典变成一个漂亮的字典,类似jw11:25158_
前面是字典的Key,后面是字典的Value


for i in img_files:
    if i[3:9] in auid.keys():
        orin = os.path.join(folder_img, i)
        dest = os.path.join(auid[i[3:9]], i)
        shutil.move(orin, dest)

终于到了最后也最激动人心的部分,判断并移动文件。
依旧循环,用i做临时变量,挨个检验img_files里面的文件,看看它是不是在我们上一步构造的字典中:

for i in img_files:
    if i[3:9] in auid.keys():

如果是,就用shutil函数把文件从orin文件夹移动到dest文件夹去。
这里用到了os库中的os.path.join函数来把文件的路径和文件名组合在一起。
毕竟你要移动文件,得提供一个完整的绝对路径才可以,类似于:

D:\try\img\82_25158_ff7d27b587d5a2f.jpg
移动到
D:\try\id\jw11
文件夹

以上就是我作为一个python初学者,成功摸索出来的整理文件夹的一点微小的经验,分享给各位,谢谢大家。

  • 27
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值