本文主要是介绍【爬虫实战】2.多线程批量下载+多线程PDF转TXT(另附2010-2021A股TXT年报下载),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.项目分析
数据来源:excel表格文件
项目需求:从excel表格中批量下载pdf版本的年报,将其命名为"股票代码_公司简称_ 年份"的格式,并全部转为txt文件。
使用语言:python
第三方库:pandas,requests, re , pdfplumber,time等。
实现思路:
- 由于企业年报文件众多,需要加入多线程来改善程序运行速度;
- 企业年报下载后体积较大,在转换为txt文件后清理原有pdf文件(可选);
- 出于效率考虑,将下载与转换操作合并,读者亦可自行调整代码分离处理。
2. 具体步骤
1.准备工作
由于数据保存在excel文件中,所以第一步从读取数据入手,本文采用pandas库处理excel表格,其他第三库亦可。
import requests
import pandas as pd
import os
import multiprocessing
import pdfplumber
import logging
import relogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')# 读取Excel文件
try:df = pd.read_excel('年报_2015.xlsx')
except Exception as e:logging.error(f"读取失败!! {e}")return
下图为原始excel文件数据,我们可以用标题名称来作为查找名,并设置对应的变量。
# 读取文件内容并存储为字典
content_dict = ((row['公司代码'], row['公司简称'], row['年份'], row['年报链接']) for _, row in df.iterrows())
# 我们分别用code, name, year, pdf_url四个变量来接受这些值
在设置好变量后,还需要设置文件目录,用来存放下载的pdf文件和我们需要的txt文件,因此我们创建两个文件夹。
# 创建存储文件的文件夹
pdf_dir = 'pdf年报'
txt_dir = 'txt年报'
try:os.makedirs(pdf_dir, exist_ok=True)os.makedirs(txt_dir, exist_ok=True)
except Exception as e:logging.error(f"创建文件夹失败!请检查权限! {e}")return
2.多线程操作
前面提到,由于表格中的文件比较庞大,直接运行速度过于缓慢,需要加入多线程来提高效率,而且笔者将下载与转换都一次性处理,在分配一个线程进行,逻辑如下图所示。
多线程具体代码如下,我们开启一个线程池(网络上有很多人讲,这里不赘述),并加入了检查文件是否存在的功能,以防止程序意外中断后,会重复进行下载操作。
如果检测到文件不存在,则调用convert()函数进行下载和转换操作。
#开启多线程
with multiprocessing.Pool() as pool:for code, name, year, pdf_url in content_dict:txt_file_name = f"{code}_{name}_{year}.txt"txt_file_path = os.path.join(txt_dir, txt_file_name)#检测文件是否已经存在if os.path.exists(txt_file_path):logging.info(f"{txt_file_name} 已存在,跳过.")else:pool.apply_async(convert, args=(code, name, year, pdf_url, pdf_dir, txt_dir))pool.close()pool.join()
3.下载和转换
接下来的任务写好convert函数即可,这里这直接给出完整代码。
def convert(code, name, year, pdf_url, pdf_dir, txt_dir):pdf_file_path = os.path.join(pdf_dir, f"{code}_{name}_{year}.pdf")txt_file_path = os.path.join(txt_dir, re.sub(r'[\\/:*?"<>|]', '', f"{code}_{name}_{year}.txt"))try:# 下载PDF文件if not os.path.exists(pdf_file_path):with requests.get(pdf_url, stream=True) as r:r.raise_for_status()with open(pdf_file_path, 'wb') as f:for chunk in r.iter_content(chunk_size=8192):f.write(chunk)# 转换PDF文件为TXT文件with pdfplumber.open(pdf_file_path) as pdf:with open(txt_file_path, 'w', encoding='utf-8') as f:for page in pdf.pages:text = page.extract_text()f.write(text)logging.info(f"{txt_file_path} 已保存.")except Exception as e:logging.error(f"出错了- {code}_{name}_{year}. {e}")else:# 删除已转换的PDF文件,以节省空间os.remove(pdf_file_path)logging.info(f"{pdf_file_path} 已被删除。")
具体来说,第一步是根据输入参数构造出 pdf文件的完整路径和 txt文件的完整路径。这里使用了 Python 的 os.path.join
函数来拼接文件路径,以及 re.sub
函数来去除文件名中的非法字符。
接下来就是用 requests
库从 pdf_url
下载文件,并将其保存在 pdf_file_path
中。下载的过程中,函数会以 8192 字节为一块,依次将文件块写入本地文件。
如果 pdf文件下载成功,我们使用 pdfplumber
库将 其转换为txt文件。
最后,函数会删除已经转换成功的 pdf文件,这样就大功告成了~
3.成果展示
经过整理,得到了如下txt文本,可以看到txt文本内容与原内容一致,便于我们之后进行词频分析。
文本挖掘是财经类学术研究的常用方式,特别是借助上市公司年报进行词频分析的应用十分广泛。
若要获取完整代码文件,或者2010-2021的txt年报下载链接,可以关注同名公众号“凌小添”回复‘年报’获取哦~
这篇关于【爬虫实战】2.多线程批量下载+多线程PDF转TXT(另附2010-2021A股TXT年报下载)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!