python 实用程序,解压中文乱码问题的解决

背景:最近在网上下载了一些视频,也不知道质量如何,但是全部是压缩包形式的(.zip压缩包的),而且解压后文件名会变成乱码。主要是压缩包很多,不然我可以使用图形界面的解压工具,这种方式是可以手动指定编码方式的,这样不会有乱码。但是压缩包太多了,手动太慢了,于是就想着用程序去执行这个。

关于 python3解压中文乱码,网上的文章可谓是一大片,真的没几个人讲清楚了。也许他们知道怎么解决了,但是没有讲清楚,导致阅读起来十分的困难,浪费时间。非常的低效。

也许有人说,既然看这些文章浪费时间,为什么不自己去看源码呢?是个好问题,但是我只是想解决这个问题,并不想深究。希望有现成的解决方案。于是去看网上的解决方案了。

不过,终究,我找到一个靠谱的博客。就是 python3 zipfile解压中文乱码问题解决这一篇,给这个作者在这里打call了先

解压乱码的解决,要分两个步骤:

  1. 对压缩包进行解压,生成文件名是乱码的文件。
  2. 对生成的文件名是乱码的文件,进行转码重命名。

可惜,网上的90%的文章没有说清楚,全是一通乱搞,来一大段乱七八糟的代码,完全不知道在写什么。

既然现在知道了这两个步骤,那么就分别执行这两步即可。

对于解压文件,可以有多种方式。我这里使用的就是zipfile这个库了。

'unzip file'
for file_name in os.listdir(srcDir):
    path = os.path.join(srcDir, file_name)
    if zipfile.is_zipfile(path):
        z = zipfile.ZipFile(path, 'r')
        z.extractall(destDir)
        z.close()
        os.remove(path)

这个程序片段的意思就是,把 srcDir目录下面的全部压缩包文件(应该只能是.zip的),全部解压到destDir目录下面。并且把已经进行过解压操作的压缩包删除掉。这时候在destDir下面肯定就生成了很多 文件名是乱码的文件

然后是对这些文件进行重命名。重命名成什么名字呢?就是不乱码的情况下的名字。

print("解压完成,开始转换编码了....")
'change charset'
for root_path, dir_names, file_names in os.walk(destDir):
    # print("xx", file_names)
    for fn in file_names:
        path = os.path.join(root_path, fn)
        if not zipfile.is_zipfile(path):
            print("before:", fn)
            try:
                fn = fn.encode('cp437').decode('gbk')
                print("after:", fn)
                new_path = os.path.join(root_path, fn)
                os.rename(path, new_path)
            except Exception as e:
                print('error:', e)

这个程序片段的意思就是对乱码的文件名进行转码重命名。

转码的关键一句就是这里了:fn = fn.encode('cp437').decode('gbk'),说明一下,这里的fn是一个字符串类型的数据,并不是所谓的File对象。

至于为什么转码是执行fn.encode('cp437').decode('gbk'),网上的文章实在是太多了,总结一句话就是,这样管用。细问起来就是,看zipfile的实现,你就明白了。

好了,憋大招了。 完整代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @name   : change_charset.py
# @author : cat
# @date   : 2018/7/13.
# @desc   : 修改文件编码
# @exec   : python3 charset/change_charset.py ~/Downloads/很多小电影/
import os
import zipfile
import sys


def get_dir_path():
    cwd = os.getcwd()
    path = cwd[0:cwd.rindex('/')] + "/dir"
    if os.path.exists(path) and os.path.isdir(path):
        return path
    else:
        raise Exception("not found this path")


def un_zip(srcDir, destDir=""):
    if not os.path.isdir(destDir) and os.path.isdir(srcDir):
        destDir = srcDir

    if os.path.isdir(srcDir) and os.path.isdir(destDir):
        'unzip file'
        for file_name in os.listdir(srcDir):
            path = os.path.join(srcDir, file_name)
            if zipfile.is_zipfile(path):
                z = zipfile.ZipFile(path, 'r')
                z.extractall(destDir)
                z.close()
                os.remove(path)
        else:

            print("解压完成,开始转换编码了....")
            'change charset'
            for root_path, dir_names, file_names in os.walk(destDir):
                # print("xx", file_names)
                for fn in file_names:
                    # srcDir 下面的所有文件(非目录),都会经过这个 path 这里了,至于为什么,你要去看 os.walk() 了。
                    path = os.path.join(root_path, fn)
                    if not zipfile.is_zipfile(path):
                        print("before:", fn)
                        try:
                            fn = fn.encode('cp437').decode('gbk')
                            print("after:", fn)
                            new_path = os.path.join(root_path, fn)
                            os.rename(path, new_path)
                        except Exception as e:
                            print('error:', e)
    else:
        raise Exception("src path is not a dir")


def remove_empty(srcDir):
    if os.path.isdir(srcDir):
        for root_path, dir_names, file_names in os.walk(srcDir):
            for dn in dir_names:
                # srcDir 下面的所有目录,都会经过这个 dir_path 这里了,至于为什么,你要去看 os.walk() 了。
                dir_path = os.path.join(root_path, dn)
                if not len(os.listdir(dir_path)):
                    os.rmdir(dir_path)
                    print("rm dir:", dir_path)


if __name__ == '__main__':
    print("input=", sys.argv[1:])
    src = sys.argv[1]
    print("src==>", os.path.isdir(src))
    un_zip(src)
    remove_empty(src)

上面有的时候使了 os.walk()这个函数,用这个的好处就是,不会漏掉子目录,或者子文件。如果只是一层的遍历,就可以直接使用os.listdir()了。

以上代码也许并不优雅,甚至不够实用。但是我希望这篇文章的确将 python解压出现乱码的解决方案讲清楚了。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值