使用Python进行文本分析-将PDF文件多进程批量处理为csv文件

开发 前端
在文本分析的过程中,将原始数据转换为TXT文件非常关键,主要出于以几个方面的考虑.

在文本分析的过程中,将原始数据转换为TXT文件非常关键,主要出于以下几个方面的考虑:

1.格式简单与统一:

  • TXT文件是一种简单的文本格式,只包含纯文本信息,不包含任何格式或样式信息。这种简单和统一的格式有助于减少在文本分析过程中可能出现的混淆或误解。
  • 其他格式的文档,如PDF或Word文档,可能包含图像、表格和其他非文本元素,还可能包含复杂的格式和样式,这些都可能干扰文本分析的过程。

2. 便于文本预处理:

  • • 文本分析通常需要对文本数据进行预处理,包括分词、去停用词、标准化等。TXT文件的简单结构使得这些预处理任务更容易执行。

  • • 与其他文件格式相比,TXT文件不包含任何复杂的格式或元数据,这有助于简化预处理步骤,减少可能出现的错误和问题。

3.兼容性:

  • • 大多数文本分析和自然语言处理(NLP)工具都能够直接处理TXT文件。将原始数据转换为TXT文件可以确保与这些工具的兼容性,从而简化分析流程。

  • • TXT文件是一种通用的文件格式,可以在不同的操作系统和软件环境中轻松处理,而不需要特定的转换或适配器。

4.节省资源:

  • • TXT文件通常比其他文件格式更小,这有助于节省存储空间和提高处理速度。较小的文件大小也意味着需要较少的计算资源来处理文本数据,从而提高分析效率。

  • • 简单的文本格式也意味着在处理时CPU和内存的消耗较低,这对于大规模文本分析任务来说是非常重要的。

5.便于文本挖掘和模式识别:

  • • 纯文本格式使得使用正则表达式和其他文本挖掘技术来识别和提取文本中的模式变得更为容易和直接。

  • • 纯文本数据也便于实现各种文本分析技术,如情感分析、主题建模和实体识别等。

6.可读性和可检查性:

  • • 人类可以直接读取和理解TXT文件,这对于检查、调试和理解文本分析的结果非常重要。

7.数据清洗:

  • • TXT文件的简单性使得更容易识别和处理缺失值、错误和其他数据质量问题,从而保证文本分析的准确性和可靠性。

将原始数据转换为TXT文件是实现有效和准确文本分析的一个基本步骤,它帮助简化和标准化文本分析流程,从而提高分析的效率和质量。以下代码可以用来将pdf文件转换为txt文件。

pdf2txt.py

#!/usr/bin/env python  # 该行命令告诉操作系统使用 Python 解释器执行此文件
import sys  # 导入sys模块,用于处理与Python解释器和运行时环境有关的操作
from pdfminer.pdfdocument import PDFDocument  # 从pdfminer模块导入PDFDocument类,用于表示PDF文档
from pdfminer.pdfparser import PDFParser  # 从pdfminer模块导入PDFParser类,用于解析PDF文档
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter  # 从pdfminer模块导入资源管理和页面解释类
from pdfminer.pdfdevice import PDFDevice, TagExtractor  # 从pdfminer模块导入PDF设备和标签提取器类
from pdfminer.pdfpage import PDFPage  # 从pdfminer模块导入PDFPage类,用于表示PDF页面
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter  # 从pdfminer模块导入转换器类,用于将PDF转换为其他格式
from pdfminer.cmapdb import CMapDB  # 从pdfminer模块导入字符映射数据库类
from pdfminer.layout import LAParams  # 从pdfminer模块导入布局分析参数类
from pdfminer.image import ImageWriter  # 从pdfminer模块导入图像写入类

# 定义主函数,argv是一个包含命令行参数的列表
def main(argv):
    import getopt  # 导入getopt模块,用于解析命令行参数
    # 定义一个显示用法的内部函数
    def usage():
        print ('usage: %s [-P password] [-o output] [-t text|html|xml|tag]'
               ' [-O output_dir] [-c encoding] [-s scale] [-R rotation]'
               ' [-Y normal|loose|exact] [-p pagenos] [-m maxpages]'
               ' [-S] [-C] [-n] [-A] [-V] [-M char_margin] [-L line_margin]'
               ' [-W word_margin] [-F boxes_flow] [-d] input.pdf ...' % argv[0])
        return 100  # 返回一个错误代码
    try:
        # 使用getopt解析命令行参数
        (opts, args) = getopt.getopt(argv[1:], 'dP:o:t:O:c:s:R:Y:p:m:SCnAVM:W:L:F:')
    except getopt.GetoptError:
        return usage()  # 如果解析失败,则显示用法并退出
    if not args: return usage()  # 如果没有提供非选项参数(例如输入文件),则显示用法并退出
    # 初始化一些变量
    debug = 0  # 调试级别
    password = b''  # PDF密码
    pagenos = set()  # 要处理的页码集
    maxpages = 0  # 最大页数
    outfile = None  # 输出文件名
    outtype = None  # 输出类型
    imagewriter = None  # 图像写入对象
    rotation = 0  # 旋转角度
    stripcontrol = False  # 是否剥离控制字符
    layoutmode = 'normal'  # 布局模式
    encoding = 'utf-8'  # 编码方式
    pageno = 1  # 页面号
    scale = 1  # 缩放因子
    caching = True  # 是否缓存
    showpageno = True  # 是否显示页面号
    laparams = LAParams()  # 布局分析参数对象
    for (k, v) in opts:  # 遍历选项和值
        if k == '-d': debug += 1  # 设置调试级别
        elif k == '-P': password = v.encode('ascii')  # 设置密码
        elif k == '-o': outfile = v  # 设置输出文件名
        elif k == '-t': outtype = v  # 设置输出类型
        elif k == '-O': imagewriter = ImageWriter(v)  # 创建图像写入对象
        elif k == '-c': encoding = v  # 设置编码方式
        elif k == '-s': scale = float(v)  # 设置缩放因子
        elif k == '-R': rotation = int(v)  # 设置旋转角度
        elif k == '-Y': layoutmode = v  # 设置布局模式
        elif k == '-p': pagenos.update(int(x)-1 for x in v.split(','))  # 更新页码集
        elif k == '-m': maxpages = int(v)  # 设置最大页数
        elif k == '-S': stripcontrol = True  # 启用剥离控制字符
        elif k == '-C': caching = False  # 禁用缓存
        elif k == '-n': laparams = None  # 禁用布局分析参数
        elif k == '-A': laparams.all_texts = True  # 启用所有文本选项
        elif k == '-V': laparams.detect_vertical = True  # 启用垂直检测选项
        elif k == '-M': laparams.char_margin = float(v)  # 设置字符边距
        elif k == '-W': laparams.word_margin = float(v)  # 设置单词边距
        elif k == '-L': laparams.line_margin = float(v)  # 设置行边距
        elif k == '-F': laparams.boxes_flow = float(v)  # 设置框流
    # 设置调试级别
    PDFDocument.debug = debug
    PDFParser.debug = debug
    CMapDB.debug = debug
    PDFPageInterpreter.debug = debug
    # 创建PDF资源管理器对象
    rsrcmgr = PDFResourceManager(caching=caching)
    # 根据输出类型和选项创建相应的PDF设备对象
    if not outtype:
        outtype = 'text'  # 默认为文本输出
        if outfile:
            if outfile.endswith('.htm') or outfile.endswith('.html'):
                outtype = 'html'  # 如果输出文件名以.htm或.html结尾,则设置为html输出
            elif outfile.endswith('.xml'):
                outtype = 'xml'  # 如果输出文件名以.xml结尾,则设置为xml输出
            elif outfile.endswith('.tag'):
                outtype = 'tag'  # 如果输出文件名以.tag结尾,则设置为tag输出
            elif outtype == 'tag':
        device = TagExtractor(rsrcmgr, outfp)  # 如果输出类型为'tag',则创建TagExtractor对象
    else:
        return usage()  # 如果不识别的输出类型,则显示用法并退出

    for fname in args:  # 遍历所有输入文件名
        with open(fname, 'rb') as fp:  # 以二进制读模式打开文件
            interpreter = PDFPageInterpreter(rsrcmgr, device)  # 创建PDF页面解释器对象
            # 遍历PDF页面,获取页面对象
            for page in PDFPage.get_pages(fp, pagenos,
                                          maxpages=maxpages, password=password,
                                          caching=caching, check_extractable=True):
                page.rotate = (page.rotate+rotation) % 360  # 设置页面旋转角度
                interpreter.process_page(page)  # 处理每个页面

    device.close()  # 关闭设备对象,释放资源
    outfp.close()  # 关闭输出文件,释放资源
    return  # 从主函数返回

# 检查此模块是否作为主模块运行
if __name__ == '__main__':
    sys.exit(main(sys.argv))  # 如果是,则调用main函数,并使用命令行参数列表作为参数

convertPDF.py

#!/usr/bin/env python3
"""
Script to convert PDFs to text files.

"""

import  unicodedata, os, pdf2txt, datetime

import multiprocessing
def convertPDFToText(i, ID, newDir, fileNamePDF):
    print('Trying to convert: ' + str(i) + ', ' + ID)  # 输出正在尝试转换的文件信息
    try:
        pdf2txt.main(['-o', newDir + '/' + ID + '.txt', fileNamePDF])  # 调用pdf2txt.main来转换PDF为文本
        print('Successfully converted: ' + ID)  # 转换成功时的输出
    except Exception as e:
        print('Failed to convert: ' + ID + f', Error: {e}')  # 转换失败时的输出

def process_pdfs(pdf_list):
    with multiprocessing.Pool(20) as pool:  # 创建一个包含20个进程的进程池
        pool.starmap(convertPDFToText, pdf_list)  # 使用starmap来并行处理pdf_list中的每个元素,每个元素都是一个元组,它将被解包为convertPDFToText的参数

if __name__ == '__main__':

    directory = '../../Data/PDF/work'
    os.chdir(directory)  # 更改当前工作目录至PDF文件目录

    # 指定保存转换后文件的目录
    newDir = '../TXT/work'
    # os.makedirs(newDir)  # 创建新目录(如果需要的话)
    print('Placing converted files in: ' + newDir)  # 输出转换后文件将被放置的目录

    pdf_list = []  # 创建一个空列表,用于保存将传递给convertPDFToText的参数元组
    i = 0  # 初始化计数器
    for fileNamePDF in os.listdir('./'):  # 遍历当前目录中的所有文件
        i += 1  # 计数器递增
        if fileNamePDF.find(".pdf") == -1:  # 如果文件不是PDF,跳过
            continue

        ID = fileNamePDF[:-4]  # 从文件名中获取ID(去掉.pdf后缀)
        if os.path.isfile('../TXT/' + ID + '.txt'):  # 如果已经存在对应的文本文件,跳过
            continue

        pdf_list.append((i, ID, newDir, fileNamePDF))  # 将参数元组添加到pdf_list中

    process_pdfs(pdf_list)  # 调用process_pdfs函数,传递pdf_list以并行处理PDF文件


责任编辑:华轩 来源: PaperCodeTips
相关推荐

2023-10-17 16:24:27

PythonCSV

2020-12-31 05:37:05

HiveUDFSQL

2023-11-28 15:18:24

Python

2023-07-05 07:36:36

SpringJava代码

2024-09-25 08:00:00

Python文件处理

2024-10-30 16:59:57

Python机器学习

2016-12-14 09:32:49

FileChanne文件复制

2023-11-28 09:00:00

机器学习少样本学习SetFit

2021-08-30 07:57:26

OpenAttack文本对抗攻击

2018-03-27 13:33:48

百度

2018-06-04 10:04:48

Python数据语言

2024-11-20 10:00:00

Python文件读写

2024-09-29 16:27:46

Python文件管理

2010-03-05 09:40:08

Python递归

2022-08-17 12:35:26

Linux sed编辑器

2010-03-12 19:29:15

python svn脚

2009-12-04 16:49:33

PHP批量导出csv文

2020-07-07 10:50:19

Python丄则表达文本

2016-11-16 15:05:42

情感分析

2024-04-28 11:39:17

绍csvkit数据分析
点赞
收藏

51CTO技术栈公众号