2022泰迪杯总结
1、基本处理
任务1.1
将压缩文件“DataA.rar”中的所有作品解压到当前文件夹的同名 子文件夹(即以每份作品的作品号为子文件夹名)中。
import os
file_path = "DataA.rar"
command='Bandizip x -y -o:./A题:竞赛作品的自动评判数据/ -target:name %s'%file_path
os.system(command)
path='./A题:竞赛作品的自动评判数据/DataA/'
for i in os.walk(path):
for k in i[2]:
file_path='./A题:竞赛作品的自动评判数据/DataA/%s'%k
command='Bandizip x -y -o:./A题:竞赛作品的自动评判数据/DataA/ -target:name %s'%(file_path)
os.system(command)
os.remove(file_path)
print(k+' ok')
Bandizip.exe 参数:
Bandizip.exe <command> [<switches>...] <archive> [<files>...] [<path_to_extract>]
<command>指令
a | 添加档案到压缩包 |
---|---|
x | 用完整路径选取档案 |
t | 测试档案的完整性 |
d | 从存档中删除文件 |
c | 创建新文件(用相同名称覆盖已有存档) |
cd | 显示“新建档案”对话框 |
rn | 重命名存档中的档案 |
l | 列出文件(仅在bz.exe上可用) |
/cmdfile | Read command lines from specified file |
<bcommand>批处理指令
bc | “使用每个文件的名称压缩多个文件/文件夹。 如果现有存档具有相同的名称,则会创建(存档名称)(2)、(存档名称)(3)...。 如果未指定目标文件夹,则会在每个原始档案所在的文件夹中创建存档。 ” |
---|---|
bx | “将多个存档文件选取到目标文件夹。 如果未指定目标文件夹,则会将文件解压缩到每个存档所在的文件夹。 ” |
bt | 测试每个归档档案的完整性。 |
开关
- | 停止开关解析 |
---|---|
-l:<0...9> | 设定压缩级别(0:存储、1:快速、5:默认值、9:最大) |
-r- | 禁用递归子目录(默认) |
-r | 启用递归子目录 |
-aoa | 无提示覆盖现有档案 |
-aos | 跳过并不覆盖现有档案 |
-aou | 自动重命名选中的文件 比如,name.txt→ name(2).txt |
-sfx:"stub path" | 创建SFX存档并设定SFX存根的完整路径 (Bandizip c -sfx:“C:\Program Files\Bandizip\bdzsfx.x86.sfx” c:\out.exe c:\src.txt) |
-zopfli | 使用Zopfil作为默认编码器(慢速) |
-p:{password} | 配置存档的密码 |
-o:{dir} | 指定目的文件夹 仅适用于x命令和批处理命令(bc、bx、bt) |
-storeroot:<yes|no> | -storeroot:yes 将根目录存储为存档的顶级文件夹 -storeroot:no 不存储存文件的顶级文件夹 |
-y | 假设所有査询都是 如果未发生错误,则在任务完成时关闭(解)压缩窗口 |
-ex:{list} | 指定压缩时要排除的档案清单 -ex:hello.txt -ex:“.bak” -ex:“.bak; .tmp" -ex:.git |
-root:{dir} | 压缩时在存档中指定根目录 (-root:top_folder) |
-fmt:{fmt} | 指定存档格式 (zip, zipx, exe, tar, tgz, lzh, iso, 7z, gz, xz) |
-v:{size} | 指定卷大小 (-v:1000000 -v:1440k -v:100MB ...) |
-cmt:{comment} | 设定ZIP档案注释 (-cmt:Hello, -cmt:“Hello World!”) |
-cmtfile:{filepath} | 指定用作ZIP文件注释的文字文件的路径 (-cmtfile:mycomment.txt, -cmtfile:“c:\test\my comment.txt”) |
-t:NN | 指定压缩时使用的CPU线程数 (-t:10, -t:1, -t:0) |
-cp:NN | 指定打开或选取文件时使用的内码表 (Bandizip x -cp:932 japanese.zip) 可用内码表的示例 - Chinese Simplified: 936 - Chinese Traditional: 950 - Japanese: 932 - Korean: 949 - UTF-8: 65001 |
-target:auto | “使用此处选取智能解压缩功能将文件选取到目的文件夹。 如果未指定目的文件夹,则会将文件解压缩到每个存档所在的文件夹。 ” |
-target:name | “将文件解压缩到目标文件夹中的存档名称文件夹。 如果未指定目标文件夹,则会将文件选取到每个存档所在文件夹中的存档名称文件夹。 ” |
-date | 将当前系统时间插入文件路径。 请参攷strftime语法。 ⁑ Bandizip.exe c -date f:\backup\%Y\%m\Backup%Y-%m-%d_%H-%M-%S.zip c:\source\ |
<switches> (仅限 Bandizip)
压缩且发送电子邮件 | |
---|---|
-target:dlg | 显示一个对话框,要求指定目标文件夹,并将文件解压缩到目标文件夹中的存档名称文件夹。 如果使用-o指定了任何文件夹,则该文件夹是对话框的默认文件夹。 |
<switches> (仅限bz.exe)
-list:v | 使用命令 l 时,显示文件的详细信息。 |
---|---|
-list:s | 使用命令 l 时,仅显示文件名。 |
-consolemode:ansi | 以ANSI格式保存输出文字txt文件。 |
-consolemode:utf8 | 以UTF-8格式保存输出文本txt文件。 |
任务1.2
在当前文件夹中新建“summary”子文件夹,在每份作品文件夹中 新建“image”子文件夹。
import os
path = r"./A题:竞赛作品的自动评判数据/DataA"
judgment_1 = os.path.exists(path + '/summary') # 判断 summary 文件夹是否存在
if (judgment_1 == False):
os.mkdir(path + '/summary')
listdir = os.listdir(path)
for dir in listdir:
if dir =="summary":
pass
else:
judgment_2 = os.path.exists(path + f"/{dir}" + '/image') # 判断 summary 文件夹是否存在
if (judgment_2 == False):
os.mkdir(path + f"/{dir}" + "/image")
listdir_dir = os.listdir(path + "/A101")
如果是读写文件的话,建议使用内置函数open()
;
如果是路径相关的操作,建议使用os
的子模块os.path
;
如果要逐行读取多个文件,建议使用fileinput
模块;
要创建临时文件或路径,建议使用tempfile
模块;
要进行更高级的文件和路径操作则应当使用shutil
模块。
os 常用操作做
os.name #操作系统相关模块的名称
"""
MAC : posix,window 。
"""
os.envrion #可以返回环境相关的信息,主要是各类环境变量
os.walk() #这个函数需要传入一个路径作为top参数,函数的作用是在以top为根节点的目录树中游走,对树中的每个目录生成一个由(dirpath, dirnames, filenames)三项组成的三元组。
os.listdir() # 列出(当前)目录下的全部路径(及文件)。该函数存在一个参数,用以指定要列出子目录的路径,默认为“.”,即“当前路径”。
os.mkdir() #新建一个路径”。
os.remove() #用于删除文件,如果指定路径是目录而非文件的话,就会抛出IsADirectoryError异常。删除目录应该使用os.rmdir()函数
os.rename() #该函数的作用是将文件或路径重命名,一般调用格式为os.rename(src, dst),即将src指向的文件或路径重命名为dst指定的名称
os.getcwd() #获取当前工作路径”
os.chdir() #切换当前工作路径为指定路径
os.path.exists() #这个函数用于判断路径所指向的位置是否存在。若存在则返回True,不存在则返回False
任务1.3
判断每份作品中是否包含文件“task2_1.xlsx”“task2_2.xlsx” 2 “task2_3.pdf”及“task3.xlsx”,每包含一个文件得 2 分,满分 8 分。
import os
path = r"./A题:竞赛作品的自动评判数据/DataA/"
data =[]
import pandas as pd
for i in os.walk(path):
for j in i[1]:
if j == "summary" or j =="image":
pass
else:
listddd = os.listdir(path+j)
count =0
if "task2_1.xlsx" in listddd:
count += 2
if 'task2_2.xlsx' in listddd:
count += 2
if 'task2_3.pdf' in listddd:
count += 2
if 'task3.xlsx' in listddd:
count += 2
data.append([j, count])
data = pd.DataFrame(data)
print(data)
data.to_excel("./result/result1_3.xlsx",index=False)
任务1.4
对每份作品提取文件“task2_3.pdf”中的图片,保存在“image” 文件夹的“XXXX_n.png”文件中,其中“XXXX”为作品号、n 为图片在文件 “task2_3.pdf”中的图片序号。提取所有作品中的图片信息,按照表 1 的格式保 存在文件夹“summary”的“result1_4.xlsx”文件中。将含有作品号 A118~A120 的结果截屏放在报告中。
import fitz
import re
import os
from PIL import Image
import math
import pandas as pd
def pdf2pic(path,pic_path,ISAN):
#正则表达式查找图片
checkXO = r"/Type(?= */XObject)"
checkIM = r"/Subtype(?= */Image)"
doc = fitz.open(path)
# 图片计数
imgcount = 0
lenXREF = doc.xref_length()
# 打印PDF的信息
print("文件名:{}, 页数: {}, 对象: {}".format(path, len(doc), lenXREF - 1))
# 遍历每一个对象
for i in range(1, lenXREF):
# 定义对象字符串
text = doc.xref_object(i)
isXObject = re.search(checkXO, text)
# 使用正则表达式查看是否是图片
isImage = re.search(checkIM, text)
# 如果不是对象也不是图片,则continue
if not isXObject or not isImage:
continue
imgcount += 1
# 根据索引生成图像
pix = fitz.Pixmap(doc, i)
# 根据pdf的路径生成图片的名称
new_name = ISAN + "_{}.png".format(imgcount)
new_name = new_name.replace(':', '')
# 如果pix.n<5,可以直接存为PNG
if pix.n < 5:
pix.save(os.path.join(pic_path, new_name))
# 否则先转换CMYK
else:
pix0 = fitz.Pixmap(fitz.csRGB, pix)
pix0.save(os.path.join(pic_path, new_name))
pix0 = None
# 释放资源
pix = None
path = "./A题:竞赛作品的自动评判数据/DataA/"
for i in os.walk(path):
for k in i[1]:
if k == 'summary' or k == 'image' :
pass
else:
listddd = os.listdir(path+k)
if 'task2_3.pdf' in listddd:
pic_path=path+k+'/image'
pdf2pic(path+k+'/task2_3.pdf', pic_path,k)
print(k+' ok')
else:
pass
data2 = []
for i in os.walk(path):
for k in i[1]:
if k=='summary' or k=='image' :
pass
else:
pic_path=path+k+'/image/'
if not os.path.getsize(pic_path):
data2.append([k,'无','无','无','无'])
else:
listddd=os.listdir(pic_path)
for j in listddd:
if 'png' in j:
pic=pic_path+j
img = Image.open(pic)
data2.append([k,j.replace('.png',''),pic,str(img.size[0] )+'*'+str(img.size[1] ),str(math.ceil(os.path.getsize(pic)/1024))+'KB'])
df=pd.DataFrame(data2,columns=['作品号','图片编号','保存路径','图片分辨率','图片文件大小'])
print(df.head())
df.to_excel("./result/result1_4.xlsx",index=False)
Python提取PDF中图片的三种方式
1、pymupdf方式
import fitz # pip install pymupdf
import re
import os
file_path = r'C:\xxx\xxx.pdf' # PDF 文件路径
dir_path = r'C:\xxx' # 存放图片的文件夹
def pdf2image1(path, pic_path):
checkIM = r"/Subtype(?= */Image)"
pdf = fitz.open(path)
lenXREF = pdf._getXrefLength()
count = 1
for i in range(1, lenXREF):
text = pdf._getXrefString(i)
isImage = re.search(checkIM, text)
if not isImage:
continue
pix = fitz.Pixmap(pdf, i)
new_name = f"img_{count}.png"
pix.writePNG(os.path.join(pic_path, new_name))
count += 1
pix = None
pdf2image1(file_path, dir_path)
2、基于 pdf2image
库的两种方法
可以简单通过 pip install pdf2image 安装,但poppler才是真正起做用的转换器,因此需要额外安装和配置:
-
windows用户必须安装
poppler for Windows
,然后将bin/文件夹添加到PATH -
Mac用户必须安装
poppler for Mac
""""一"""
from pdf2image import convert_from_path,convert_from_bytes
import tempfile
from pdf2image.exceptions import PDFInfoNotInstalledError, PDFPageCountError, PDFSyntaxError
import os
file_path = r'C:\xxx\xxx.pdf' # PDF 文件路径
dir_path = r'C:\xxx' # 存放图片的文件夹
def pdf2image2(file_path, dir_path):
images = convert_from_path(file_path, dpi=200)
for image in images:
if not os.path.exists(dir_path):
os.makedirs(dir_path)
image.save(file_path + f'\img_{images.index(image)}.png', 'PNG')
pdf2image2(file_path, dir_path)
"""二"""
from pdf2image import convert_from_path,convert_from_bytes
import tempfile
from pdf2image.exceptions import PDFInfoNotInstalledError, PDFPageCountError, PDFSyntaxError
import os
file_path = r'C:\xxx\xxx.pdf' # PDF 文件路径
dir_path = r'C:\xxx' # 存放图片的文件夹
def pdf2image3(file_path, dir_path):
images = convert_from_bytes(open(file_path, 'rb').read())
for image in images:
if not os.path.exists(dir_path):
os.makedirs(dir_path)
image.save(file_path + f'\img_{images.index(image)}.png', 'PNG')
pdf2image3(file_path, dir_path)
核心方法covert_from_bytes
包含大量参数。常用参数如下:
参数 | 意义 |
---|---|
pdf_path | PDF 文档路径 |
dpi | 图像质量(如果是学术期刊杂志常见 300dpi) |
output_folder | 将生成的图像写入文件夹(而不是直接写入内存) |
first_page | 起始转换页数 |
last_page | 转换至哪一页 |
fmt | 图像格式,可以指定为 png,默认为 ppm |
thread_count | 允许参与转换的线程数 |
userpw | PDF 的密码 |
output_file | 输出文件名 |
poppler_path | 指定 poppler 的安装路径,一开始配置好就无需指定 |
值得一提的是thread_count
参数,可以启动多线程会大大加快转换速度,尤其是 PDF 页面较多时。有兴趣的读者可以做尝试。
3、批量提取图片
pip install fitz
pip install pymupdf
def save_pdf_img(path,save_path):
'''
path: pdf的路径
save_path : 图片存储的路径
'''
# 使用正则表达式来查找图片
checkXO = r"/Type(?= */XObject)"
checkIM = r"/Subtype(?= */Image)"
# 打开pdf
doc = fitz.open(path)
# 图片计数
imgcount = 0
# 获取对象数量长度
lenXREF = doc.xref_length()
# 打印PDF的信息
print("文件名:{}, 页数: {}, 对象: {}".format(path, len(doc), lenXREF - 1))
# 遍历每一个图片对象
for i in range(1, lenXREF):
# 定义对象字符串
text = doc.xref_object(i)
# print(i,text)
isXObject = re.search(checkXO, text)
# 使用正则表达式查看是否是图片
isImage = re.search(checkIM, text)
# 如果不是对象也不是图片,则continue
if not isXObject or not isImage:
continue
imgcount += 1
# 根据索引生成图像
pix = fitz.Pixmap(doc, i)
# 根据pdf的路径生成图片的名称
new_name = path.replace('\\', '_') + "_img{}.png".format(imgcount)
new_name = new_name.replace(':', '')
# 如果pix.n<5,可以直接存为PNG
if pix.n < 5:
pix.writePNG(os.path.join(save_path, new_name))
# 否则先转换CMYK
else:
pix0 = fitz.Pixmap(fitz.csRGB, pix)
pix0.writePNG(os.path.join(save_path, new_name))
pix0 = None
# 释放资源
pix = None
print("提取了{}张图片".format(imgcount))
# pdf路径
path = r'/Users/wangwangyuqing/Desktop/data/img.pdf'
save_path = r'/Users/wangwangyuqing/Desktop/data'
save_pdf_img(path,save_path)