三小时爬取四万份年报

三小时爬取四万份年报

本文爬虫的任务提交速度以及下载速度:

三小时爬取四万份年报

三小时爬取四万份年报

; 年报文本分析

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

《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

进行一些初始化操作


    file_path = r'E:\python\firmreport_spider2.0\公司竞争战略指标_2001_2019.xlsx'

    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

    q = Queue()

    num_threads = 8

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


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)

        xw.Range((info[4]+1, 7)).value = 'YES'

        q.task_done()

最后写一个总的流程

if __name__ == '__main__':

    file_path = r'E:\python\firmreport_spider2.0\公司竞争战略指标_2001_2019.xlsx'

    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

    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()

所有的代码如下:

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)

        xw.Range((info[4]+1, 7)).value = 'YES'
        q.task_done()

if __name__ == '__main__':

    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

    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()

Original: https://blog.csdn.net/a17695740817/article/details/121297501
Author: 金星python
Title: 三小时爬取四万份年报

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/697152/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球