从互联网上批量下载PDF文件

功能描述

从互联网上批量下载pdf文件,并保存在文件夹中

准备工作

pdf的互联网链接保存在csv文件中,这个文件中第一列是要保存的文件名称,第二列是pdf链接

Python代码

import csv
import requests
import os
import re
from tqdm import tqdm
import threading


# 定义一个函数来清除无效字符
def clean_filename(filename):
    cleaned_filename = re.sub(r'[\\/:"*?<>|]', '', filename)
    return cleaned_filename


def download_file(file_name, file_url, file_path):
    # 发起请求并下载文件
    response = requests.get(file_url, stream=True)
    response.raise_for_status()

    total_size = int(response.headers.get('content-length', 0))
    block_size = 8192  # 每次读取的数据块大小
    progress_bar = tqdm(total=total_size, unit='iB', unit_scale=True)

    with open(file_path, 'wb') as file:
        for chunk in response.iter_content(chunk_size=block_size):
            if chunk:
                file.write(chunk)
                progress_bar.update(len(chunk))
    progress_bar.close()
    print(f'{file_name} 下载完成')


def download():
    # 设定存储路径
    download_dir = 'download'

    # 打开 csv 文件并读取数据
    with open('UAI 2023.csv', newline='', encoding='utf-8-sig') as csvfile:
        reader = csv.DictReader(csvfile)

        # 创建一个列表来保存线程对象
        threads = []

        # 逐行读取数据
        for row in reader:
            # 修改file_name变量,使用clean_filename函数来清除无效字符
            file_name = clean_filename(row['pdf_name'])
            file_url = row['pdf_link']
            file_path = os.path.join(download_dir, file_name + '.pdf')

            # 创建线程对象,并将下载函数作为目标
            thread = threading.Thread(target=download_file, args=(file_name, file_url, file_path))
            threads.append(thread)

            # 启动线程
            thread.start()

        # 等待所有线程完成
        for thread in threads:
            thread.join()

    print('所有文件下载完成')


if __name__ == '__main__':
    download()

代码解释

这段代码实现了一个简单的文件下载器,主要包括以下功能:

  1. 导入了必要的模块:csv 用于处理 CSV 文件,requests 用于发起 HTTP 请求,os 用于处理文件路径,re 用于正则表达式操作,tqdm 用于显示下载进度,threading 用于多线程下载。

  2. 定义了 clean_filename 函数,用于清除文件名中的无效字符,以便在保存文件时使用。

  3. 定义了 download_file 函数,用于下载文件。函数接受文件名、文件 URL 和文件路径作为参数,使用 requests 库发起请求并下载文件。在下载过程中会显示下载进度条。

  4. 定义了 download 函数,主要逻辑是打开名为 ‘UAI 2023.csv’ 的 CSV 文件,逐行读取数据,并针对每一行启动一个新的线程来下载文件。在循环结束后,等待所有线程执行完毕。

  5. 在主程序中调用 download 函数,开始执行文件下载操作。

总体而言,这段代码使用多线程下载文件,提高了下载效率,同时通过定义清除无效字符的函数和显示下载进度条的功能,使文件下载更加稳定和用户友好。

逐行解释

下面逐行解释这段代码的细节:

  1. import csv:导入 CSV 文件处理模块。

  2. import requests:导入请求库,用于发起 HTTP 请求。

  3. import os:导入 os 模块,用于处理文件路径。

  4. import re:导入正则表达式模块。

  5. from tqdm import tqdm:从 tqdm 模块中导入显示进度条的函数。

  6. import threading:导入多线程处理模块。

  7. def clean_filename(filename)::定义清除无效字符的函数。该函数接受一个文件名参数,使用正则表达式将其中的无效字符替换为空格,并返回清理后的文件名。

  8. cleaned_filename = re.sub(r'[\\/:"*?<>|]', '', filename):使用正则表达式将文件名中的无效字符替换为空格,并将结果赋值给变量 cleaned_filename。

  9. return cleaned_filename:返回清理后的文件名。

  10. def download_file(file_name, file_url, file_path)::定义下载文件的函数。该函数接受三个参数:文件名、文件 URL 和文件路径。

  11. response = requests.get(file_url, stream=True):使用 requests 库发起 GET 请求,并设置 stream 参数为 True,以便能够按块读取数据。

  12. response.raise_for_status():如果请求失败,则抛出异常。这是一种检查请求是否成功的常见方法。

  13. total_size = int(response.headers.get('content-length', 0)):获取要下载的文件的总大小,以字节为单位。

  14. block_size = 8192:设置每次读取的块大小为 8192 字节。

  15. progress_bar = tqdm(total=total_size, unit='iB', unit_scale=True):使用 tqdm 函数创建一个进度条对象,total 参数设置为要下载的文件总大小,unit 参数设置为 iB,表示使用 IEC 标准来显示文件大小。

  16. with open(file_path, 'wb') as file::打开文件,以二进制写入模式打开,将文件名和路径传递给 open 函数,使用 with 语句来确保文件在处理完毕后能够正确关闭。

  17. for chunk in response.iter_content(chunk_size=block_size)::循环遍历 response 对象,使用 iter_content 方法按块读取数据,并设置 chunk_size 参数为上面设置的块大小。

  18. if chunk::如果读取到了数据块,则执行下一步操作。

  19. file.write(chunk):将读取到的数据块写入文件。

  20. progress_bar.update(len(chunk)):更新进度条,将已下载的字节数添加到进度条中。

  21. progress_bar.close():关闭进度条。

  22. print(f'{file_name} 下载完成'):在控制台输出下载完成信息。

  23. def download()::定义文件下载主函数。

  24. download_dir = 'download':设置要保存文件的目录。

  25. with open('UAI 2023.csv', newline='', encoding='utf-8-sig') as csvfile::打开 CSV 文件,使用 with 语句确保文件在处理完毕后能够正确关闭。

  26. reader = csv.DictReader(csvfile):将文件内容读入到一个字典迭代器中,以便能够按行读取数据。

  27. threads = []:创建一个空列表来保存线程对象。

  28. for row in reader::按行遍历 CSV 文件中的数据。

  29. file_name = clean_filename(row['pdf_name']):使用定义的清除无效字符的函数对文件名进行清理。

  30. file_url = row['pdf_link']:获取文件下载链接。

  31. file_path = os.path.join(download_dir, file_name + '.pdf'):使用 os 模块的 join 函数创建文件路径,将目录和文件名连接起来,并添加 .pdf 扩展名。

  32. thread = threading.Thread(target=download_file, args=(file_name, file_url, file_path)):创建一个新的线程,将下载函数作为目标,将文件名、文件 URL 和文件路径作为参数传递给该函数。

  33. threads.append(thread):将新创建的线程对象添加到列表中。

  34. thread.start():启动线程。

  35. for thread in threads::等待所有线程执行完毕。

  36. thread.join():等待线程执行完毕。

  37. print('所有文件下载完成'):在控制台输出所有文件下载完成的信息。

  38. if __name__ == '__main__'::判断是否为主程序。

  39. download():调用 download 函数,开始执行文件下载操作。

  • 26
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值