三小时爬取四万份年报

您所在的位置:网站首页 巨潮资讯可以下载所有年报吗 三小时爬取四万份年报

三小时爬取四万份年报

2023-10-27 12:24| 来源: 网络整理| 查看: 265

三小时爬取四万份年报

本文爬虫的任务提交速度以及下载速度: 在这里插入图片描述

在这里插入图片描述

年报文本分析

如果你有年报文本分析需求,首先你就要获取上市公司年报 关于上市公司年报的爬虫已经有很多篇了,如下:

《30行代码轻松爬取全部A股公司年报》 《实战演练-爬取深交所年报》 《【爬虫】用Python爬取公司年报》 《Python爬取上交所年报并下载》 后三个太麻烦了,需要分析网页,爬取链接,第一个最简单,因为他直接给出了所有公司年报的下载链接(好人一生平安),秉承着能复制粘贴绝不自己写的原则,选了第一个。但是这几个爬虫都有两个问题: 1.如果你爬着爬着中断了,需要重新爬取 2.都是单线程,尤其是这种网络IO,效率低

因此,本文对第一个爬虫使用了多线程进行了改写,还使用了xlwings记录实时下载状态。

爬虫思路

先看一下第一个爬虫给出的excel文件: 在这里插入图片描述 其实我们只需要前六列,因此我们将其复制粘贴到Excel中,再加入第七列标题state,以后用来记录下载状态。 注意:电脑上必须要有微软的office,否则后面爬虫没法用 在这里插入图片描述 简单来讲,我们的爬虫分为这几部分: 1.读取excel数据,获取下载链接 2.发起请求,接收pdf数据 3.把pdf进行存储 我们可以简化一下: 1.读取excel数据,获取下载链接 2.发起请求,接收pdf数据,把pdf进行存储 所以单线程爬虫总共分两步,但是每个文件下载都要等十几秒,效率非常低。

本文使用多线程的思路,多线程就是一心多用,如果你需要扫地,还需要蒸米饭,那你可以先把电饭煲打开,然后去扫地。当你做的每件事情都要等待,一心多用就会大大提高效率。

本文的思路是,把每个下载当成一个任务,先找个“任务管理员”,我们叫他Queue(),把所有下载任务全都告诉他,然后我们一心八用(开八门开八个线程),找Queue()要任务,执行任务,再去要任务,直到Queue()的任务全都派出去执行完了。代码如下:

先把需要的库导入,不需要问为什么

import xlwings as xw import requests from queue import Queue import threading import os import time

进行一些初始化操作

# 把我们的excel路径写下来 file_path = r'E:\python\firmreport_spider2.0\公司竞争战略指标_2001_2019.xlsx' # 初始化,打开excel,统计行列数 wb = xw.Book(file_path) sht = wb.sheets['公司竞争战略指标_2001_2019'] #等待一会,打开太慢了 time.sleep(6) # 获取行列数 info = sht.used_range rows = info.last_cell.row columns = info.last_cell.column #创建一个任务管理员Queue() q = Queue() #设置八个线程 num_threads = 8

读取数据,提交给任务管理员q

# 把所有未下载链接提交给任务管理员q,等线程接取任务 def put_queue(): #把excel的所有数据给lists lists = sht.range('A1').expand('table').value #从第二行开始,逐行读取,直到最后一行 for i in range(1, rows): #如果第i行的第7列(state那列)是空的,也就是没下载,把那行的数据提交给q if not lists[i][6]: code = str(int(lists[i][0])) firm = lists[i][1].replace("*", "") url = lists[i][4] year = lists[i][2].year n = i q.put([code, firm, year, url, n]) print(code, firm, year, url, n)

定义存储路径和文件名称

# 这个函数只要拿到code,firm,year就能返回存储路径+文件名 def get_filepath(code, firm, year): file_path = 'E:\\python\\firmreport_spider2.0\\下载年报' file_name = "{}-{}-{}年年度报告.pdf".format(code, firm, year) file_full_name = os.path.join(file_path, file_name) return file_full_name

发送请求,进行下载,然后存储

# 拿到下载链接和存储路径,就会自动下载并存储 def download_pdf(url, file_full_name): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60'} res = requests.get(url, headers=headers) with open(file_full_name, "wb") as fp: for chunk in res.iter_content(chunk_size=1024): if chunk: fp.write(chunk)

定义一个线程需要做的事,取任务,设置下载路径并制定文件名,下载存储,队列任务减一

#利用前面的函数定义一个线程需要做的事,取任务,设置下载路径并制定文件名,下载存储,队列任务减一 def single(): while True: #找q要任务信息 info = q.get() #根据任务信息先把文件全名和路径写好 file_full_name = get_filepath(info[0], info[1], info[2]) #把链接和路径给下载器,自动下载和存储 download_pdf(info[3], file_full_name) #下载成功后在excel中记录为YES xw.Range((info[4]+1, 7)).value = 'YES' #q里的任务数减一 q.task_done()

最后写一个总的流程

if __name__ == '__main__': # 把我们的excel路径写下来 file_path = r'E:\python\firmreport_spider2.0\公司竞争战略指标_2001_2019.xlsx' # 初始化,打开excel,统计行列数 wb = xw.Book(file_path) sht = wb.sheets['公司竞争战略指标_2001_2019'] #等待一会,打开太慢了 time.sleep(6) # 获取行列数 info = sht.used_range rows = info.last_cell.row columns = info.last_cell.column #创建一个任务管理员Queue() q = Queue() #设置八个线程 num_threads = 8 #开启八门 for i in range(num_threads): t = threading.Thread(target=single) t.daemon = True t.start() # 启动任务管理员 put_queue() #等待q里的任务没了结束 q.join()

所有的代码如下:

import xlwings as xw import requests from queue import Queue import threading import os import time # 把所有未下载链接放入队列,放入队列就变成了任务,等线程接取任务 def put_queue(): lists = sht.range('A1').expand('table').value for i in range(1, rows): if not lists[i][6]: code = str(int(lists[i][0])) firm = lists[i][1].replace("*", "") url = lists[i][4] year = lists[i][2].year n = i q.put([code, firm, year, url, n]) print(code, firm, year, url, n) # 定义存储路径和文件名称 def get_filepath(code, firm, year): file_path = 'E:\\python\\firmreport_spider2.0\\下载年报' file_name = "{}-{}-{}年年度报告.pdf".format(code, firm, year) file_full_name = os.path.join(file_path, file_name) return file_full_name # 发送请求,进行下载,然后存储 def download_pdf(url, file_full_name): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60'} res = requests.get(url, headers=headers) with open(file_full_name, "wb") as fp: for chunk in res.iter_content(chunk_size=1024): if chunk: fp.write(chunk) #定义一个线程需要做的事,取任务,设置下载路径并制定文件名,下载存储,队列任务减一 def single(): while True: info = q.get() file_full_name = get_filepath(info[0], info[1], info[2]) download_pdf(info[3], file_full_name) #下载成功后记录为YES xw.Range((info[4]+1, 7)).value = 'YES' q.task_done() if __name__ == '__main__': # 初始化,打开excel,统计行列数 file_path = r'E:\python\firmreport_spider2.0\公司竞争战略指标_2001_2019.xlsx' wb = xw.Book(file_path) sht = wb.sheets['公司竞争战略指标_2001_2019'] time.sleep(3) # 获取行列数 info = sht.used_range rows = info.last_cell.row columns = info.last_cell.column # print(rows,columns) q = Queue() num_threads = 8 for i in range(num_threads): t = threading.Thread(target=single) t.daemon = True t.start() # 启动队列 put_queue() q.join()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3