Python爬虫实现2003年~2022年三万+个公司年报的智能抓取与关键词次数统计(第二部分代码-共三部分):将下载好的未加密的PDF年报转为TXT文件并将加密的PDF文件解密后转为TXT文件

    本项目是全程运用Python实现的,分为三个代码实现三部分功能,本次讲解的是第二部分代码:将下载好的未加密的PDF年报转为TXT文件并将加密的PDF文件解密后转为TXT文件,想要代码和统计好的年报EXCEL文档的可以私聊我或者从最后的第三部分文章链接里的GitHub网站中下载哦 ❛‿˂̵✧

import importlib
import sys
import time
import os
import re

from PyPDF2 import PdfReader #pdf的读取方法
from PyPDF2 import PdfWriter #pdf的写入方法
"""
如果是python2的将上面的PdfReader和PdfWriter改为
PdfFileReader和PDFfileWriter即可
"""
from Crypto.Cipher import AES #高加密的方法,要引入不然会报错

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
from pdfminer.pdfpage import PDFTextExtractionNotAllowed

importlib.reload(sys)
time1 = time.time()

    这部分代码是实现模块的导入和代码运行时间赋值,如果没有安装库的则需要安装一下对应的Python的库。

def get_reader(filename, password):
    try:
        old_file = open(filename, 'rb')
        print('解密开始...')
    except Exception as err:
        return print('文件打开失败!' + str(err))

    pdf_reader = PdfReader(old_file)

    if pdf_reader.is_encrypted:
        if password is None:
            return print('文件被加密,需要密码!--{}'.format(filename))
        #else:
            #if pdf_reader.decrypt(password) == 1:
                #return print('密码不正确!--{}'.format(filename))

    if old_file in locals():
        old_file.close()

    return pdf_reader

        这个函数的作用是打开一个PDF文件,并进行解密操作(如果需要)。函数接受两个参数:文件名(filename)和密码(password)。

        首先,函数尝试以二进制模式打开指定的文件,并将其赋值给变量old_file。如果文件打开失败,函数会返回一个错误信息。

         接下来,函数使用PdfReader类创建一个PDF阅读器对象pdf_reader,该对象用于读取和操作PDF文件。

        如果PDF文件被加密,函数会检查是否提供了密码。如果没有提供密码,函数会返回一个提示信息,指示文件需要密码才能解密。

        如果提供了密码,函数会尝试使用该密码对PDF文件进行解密操作。如果密码不正确,函数会返回一个提示信息,指示密码不正确。

        最后,函数会关闭打开的文件,并返回pdf_reader对象,以便后续对PDF文件进行读取和操作。

        总的来说,这个函数的作用是打开并解密一个PDF文件,并返回一个PdfReader对象,以便后续对文件进行读取和操作。

def deception_pdf(filename, password, decrypted_filename=None):
    print('正在生成解密...')
    pdf_reader = get_reader(filename, password)
    if pdf_reader is None:
        return print("无内容读取")

    if not pdf_reader.is_encrypted:
        return print('文件没有被加密,无需操作')

    pdf_writer = PdfWriter()

    for page in pdf_reader.pages:
        pdf_writer.add_page(page)

    if decrypted_filename is None:
        decrypted_filename = "".join(filename.split('.')[:-1]) +'.pdf'
        print("解密文件已生成:{}".format(decrypted_filename))

    with open(decrypted_filename, 'wb') as output_pdf:
        pdf_writer.write(output_pdf)

        这个函数的作用是对加密的PDF文件进行解密,并生成一个解密后的PDF文件。

        函数接受三个参数:文件名(filename)、密码(password)和解密后的文件名(decrypted_filename,默认为None)。

        首先,函数会调用get_reader函数获取一个PdfReader对象,该对象用于读取和操作PDF文件。如果get_reader函数返回None,表示无法读取内容,函数会返回一个提示信息。

        接下来,函数会检查PDF文件是否被加密。如果没有加密,函数会返回一个提示信息,指示文件无需操作。

        然后,函数创建一个PdfWriter对象pdf_writer,用于写入解密后的PDF文件。

        接着,函数遍历原始PDF文件的每一页,并将其添加到pdf_writer中。

        如果没有提供解密后的文件名(decrypted_filename),函数会根据原始文件名生成一个新的文件名,并打印提示信息。

        最后,函数使用with语句打开解密后的文件,并使用pdf_writer将解密后的PDF内容写入文件中。

        总的来说,这个函数的作用是对加密的PDF文件进行解密,并生成一个解密后的PDF文件。如果文件没有加密,则不进行任何操作。函数返回None或打印相应的提示信息。

def parse(pdf_path, txt_path):
    # 解析PDF文本,并保存到TXT文件中
    fp = open(pdf_path, 'rb')
    # 用文件对象创建一个PDF文档分析器
    parser = PDFParser(fp)
    # 创建一个PDF文档
    doc = PDFDocument(parser)
    # 连接分析器,与文档对象
    parser.set_document(doc)
    #doc.set_parser(parser)

    # 提供初始化密码,如果没有密码,就创建一个空的字符串
    #doc.initialize()

    # 检测文档是否提供txt转换,不提供就忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        # 创建PDF,资源管理器,来共享资源
        rsrcmgr = PDFResourceManager()
        # 创建一个PDF设备对象
        laparams = LAParams()
        device = PDFPageAggregator(rsrcmgr, laparams=laparams)
        # 创建一个PDF解释器对象
        interpreter = PDFPageInterpreter(rsrcmgr, device)

        # 循环遍历列表,每次处理一个page内容
        # doc.get_pages() 获取page列表
        for i, page in enumerate(PDFPage.create_pages(doc)):
            interpreter.process_page(page)
            # 接受该页面的LTPage对象
            layout = device.get_result()
            # 这里layout是一个LTPage对象 里面存放着 这个page解析出的各种对象
            # 一般包括LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等等
            # 想要获取文本就获得对象的text属性,
            for x in layout:
                if (isinstance(x, LTTextBoxHorizontal)):
                    with open(txt_path, 'a+', encoding='utf-8') as f:
                        results = x.get_text()
                        print(results)
                        f.write(results + "\n")

        这个函数的作用是解析PDF文本,并将解析结果保存到TXT文件中。

        函数接受两个参数:PDF文件路径(pdf_path)和TXT文件路径(txt_path)。

        首先,函数以二进制模式打开PDF文件,并将其赋值给文件对象fp。

        接下来,函数使用PDFParser类创建一个PDF文档分析器对象parser,并将文件对象与其连接。

        然后,函数使用PDFDocument类创建一个PDF文档对象doc,并将分析器与其连接。

        如果PDF文档需要密码进行解析,可以在此处提供密码进行初始化,但代码中被注释掉了。

        接着,函数检查文档是否可以提取文本内容。如果不可提取,则抛出PDFTextExtractionNotAllowed异常。

        如果文档可以提取文本内容,函数会创建一个PDF资源管理器对象rsrcmgr,并创建一个PDF设备对象device,用于处理页面内容。

        然后,函数创建一个PDF解释器对象interpreter,并将资源管理器和设备对象与其连接。

        接下来,函数使用循环遍历PDF文档的每一页,通过解释器处理每一页的内容。

        在循环中,函数使用设备对象的get_result方法获取页面解析结果的布局对象layout。

        然后,函数遍历布局对象中的每个对象x,如果对象是LTTextBoxHorizontal类型(水平文本框),则将文本内容写入TXT文件。

        最后,函数关闭TXT文件。

        总的来说,这个函数的作用是解析PDF文本,并将解析结果保存到TXT文件中。函数返回None。

def process_files(folder_path):

   # 获取文件总数
   total_files = len([filename for filename in os.listdir(folder_path) if filename.endswith('.pdf')])
   processed_files = 0

   # 遍历文件夹中的所有pdf文件
   for filename in os.listdir(folder_path):
       if filename.endswith('.pdf'):
           # 解析文件名,提取股票代码、公司简称和年份

           match = re.match(r'^(\d{6})_(.*?)_(\d{4})\.pdf$', filename)
           #if match:
               #stock_code = match.group(1)
               #company_name = match.group(2)
               #year = match.group(3)
           pdf_path = 'C://Users\末路歧途\Desktop\LC 爬取\年报PDF版\\'+filename

           deception_pdf(pdf_path, '')#解密PDF

           txt_path = 'C://Users\末路歧途\Desktop\LC 爬取\年报TXT版\\'+match.group(1)+'_'+match.group(2)+'_'+match.group(3)+'.txt'
           parse(pdf_path, txt_path)
           time2 = time.time()
           print("总共消耗时间为:", time2 - time1)

        这个函数的作用是处理一个文件夹中的所有PDF文件。

        函数接受一个参数:文件夹路径(folder_path)。

        首先,函数使用os.listdir方法获取文件夹中所有的文件名,并使用列表推导式筛选出以".pdf"结尾的文件名,然后计算文件总数。

        接下来,函数使用循环遍历文件夹中的每个文件名。

        如果文件名以".pdf"结尾,函数会使用正则表达式匹配文件名,提取股票代码、公司简称和年份的信息。

        然后,函数构建PDF文件的完整路径,并调用deception_pdf函数对PDF文件进行解密(此处的函数调用被注释掉了)。

        接着,函数构建TXT文件的完整路径,并调用parse函数解析PDF文件,并将解析结果保存到TXT文件中。

        最后,函数打印总共消耗的时间。

        总的来说,这个函数的作用是处理一个文件夹中的所有PDF文件,包括解密PDF文件并将解析结果保存到TXT文件中。函数返回None。

if __name__ == '__main__':
    process_files('C://Users\末路歧途\Desktop\LC 爬取\年报PDF版')

        这段代码是一个主程序的入口点,用于执行`process_files`函数来处理指定文件夹中的PDF文件。

        首先,'__name__'是一个内置变量,用于表示当前模块的名称。当模块直接被执行时,`__name__`的值为''__main__''。

        所以,'if __name__ == '__main__':'这行代码的作用是判断当前模块是否直接被执行。

        如果当前模块是直接被执行的,那么会执行`process_files`函数来处理指定文件夹中的PDF文件。

        'process_files'函数的作用是处理一个文件夹中的所有PDF文件,具体的功能在之前的回答中已经解释过了。

        最后,通过传入文件夹路径' 'C://Users\末路歧途\Desktop\LC 爬取\年报PDF版' '调用'process_files'函数来处理该文件夹中的PDF文件。

        总的来说,这段代码的作用是执行`process_files`函数来处理指定文件夹中的PDF文件。

PS:代码中的'C://Users\末路歧途\Desktop\LC 爬取\年报PDF版'和'C://Users\末路歧途\Desktop\LC 爬取\年报TXT版'需要改成自己的PDF年报路径和自己的TXT年报路径。

总体代码如下代码:

import importlib
import sys
import time
import os
import re

from PyPDF2 import PdfReader #pdf的读取方法
from PyPDF2 import PdfWriter #pdf的写入方法
"""
如果是python2的将上面的PdfReader和PdfWriter改为
PdfFileReader和PDFfileWriter即可
"""
from Crypto.Cipher import AES #高加密的方法,要引入不然会报错

from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
from pdfminer.pdfpage import PDFTextExtractionNotAllowed

importlib.reload(sys)
time1 = time.time()

def get_reader(filename, password):
    try:
        old_file = open(filename, 'rb')
        print('解密开始...')
    except Exception as err:
        return print('文件打开失败!' + str(err))

    pdf_reader = PdfReader(old_file)

    if pdf_reader.is_encrypted:
        if password is None:
            return print('文件被加密,需要密码!--{}'.format(filename))
        #else:
            #if pdf_reader.decrypt(password) == 1:
                #return print('密码不正确!--{}'.format(filename))

    if old_file in locals():
        old_file.close()

    return pdf_reader

def deception_pdf(filename, password, decrypted_filename=None):
    print('正在生成解密...')
    pdf_reader = get_reader(filename, password)
    if pdf_reader is None:
        return print("无内容读取")

    if not pdf_reader.is_encrypted:
        return print('文件没有被加密,无需操作')

    pdf_writer = PdfWriter()

    for page in pdf_reader.pages:
        pdf_writer.add_page(page)

    if decrypted_filename is None:
        decrypted_filename = "".join(filename.split('.')[:-1]) +'.pdf'
        print("解密文件已生成:{}".format(decrypted_filename))

    with open(decrypted_filename, 'wb') as output_pdf:
        pdf_writer.write(output_pdf)


def parse(pdf_path, txt_path):
    # 解析PDF文本,并保存到TXT文件中
    fp = open(pdf_path, 'rb')
    # 用文件对象创建一个PDF文档分析器
    parser = PDFParser(fp)
    # 创建一个PDF文档
    doc = PDFDocument(parser)
    # 连接分析器,与文档对象
    parser.set_document(doc)
    #doc.set_parser(parser)

    # 提供初始化密码,如果没有密码,就创建一个空的字符串
    #doc.initialize()

    # 检测文档是否提供txt转换,不提供就忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        # 创建PDF,资源管理器,来共享资源
        rsrcmgr = PDFResourceManager()
        # 创建一个PDF设备对象
        laparams = LAParams()
        device = PDFPageAggregator(rsrcmgr, laparams=laparams)
        # 创建一个PDF解释器对象
        interpreter = PDFPageInterpreter(rsrcmgr, device)

        # 循环遍历列表,每次处理一个page内容
        # doc.get_pages() 获取page列表
        for i, page in enumerate(PDFPage.create_pages(doc)):
            interpreter.process_page(page)
            # 接受该页面的LTPage对象
            layout = device.get_result()
            # 这里layout是一个LTPage对象 里面存放着 这个page解析出的各种对象
            # 一般包括LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等等
            # 想要获取文本就获得对象的text属性,
            for x in layout:
                if (isinstance(x, LTTextBoxHorizontal)):
                    with open(txt_path, 'a+', encoding='utf-8') as f:
                        results = x.get_text()
                        print(results)
                        f.write(results + "\n")

def process_files(folder_path):

   # 获取文件总数
   total_files = len([filename for filename in os.listdir(folder_path) if filename.endswith('.pdf')])
   processed_files = 0

   # 遍历文件夹中的所有pdf文件
   for filename in os.listdir(folder_path):
       if filename.endswith('.pdf'):
           # 解析文件名,提取股票代码、公司简称和年份

           match = re.match(r'^(\d{6})_(.*?)_(\d{4})\.pdf$', filename)
           #if match:
               #stock_code = match.group(1)
               #company_name = match.group(2)
               #year = match.group(3)
           pdf_path = 'C://Users\末路歧途\Desktop\LC 爬取\年报PDF版\\'+filename

           deception_pdf(pdf_path, '')#解密PDF

           txt_path = 'C://Users\末路歧途\Desktop\LC 爬取\年报TXT版\\'+match.group(1)+'_'+match.group(2)+'_'+match.group(3)+'.txt'
           parse(pdf_path, txt_path)
           time2 = time.time()
           print("总共消耗时间为:", time2 - time1)

if __name__ == '__main__':
    process_files('C://Users\末路歧途\Desktop\LC 爬取\年报PDF版')

    第二部分代码实现了将下载好的未加密的PDF年报转为TXT文件并将加密的PDF文件解密后转为TXT文件,和其他的两部分是相呼应的。下面是另外两部分的博客链接,想看的友友们可以自行查看哦!

第一部分博客链接:Python爬虫实现2003年~2022年三万+个公司年报的智能抓取与关键词次数统计(第一部分代码-共三部分):从统计好的EXCEL表格中自动进行公司年报的下载地址的捕捉并下载年报PDF-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_57339667/article/details/133849833?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22133849833%22%2C%22source%22%3A%22m0_57339667%22%7D

第三部分博客链接:Python爬虫实现2003年~2022年三万+个公司年报的智能抓取与关键词次数统计(第三部分代码-共三部分):从每一个生成的TXT年报文件中搜索自己制定的关键词并统计对应的出现次数到EXCEL表格中-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_57339667/article/details/134349504

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的工作流程包括以下几个关键步骤: URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。 解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。 反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。 爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值