利用Python批量下载学生PDF教材

作为一个业余爱好者,一直在优快云学习,终于有机会也来写一篇记录一下这两天的成果。
最近因为网课上线,教育部公开了义务教育用书的电子版本,出于好奇打开看了看,看网站上不仅可以在线观看,还能够下载,于是下载两本看看。细看这次提供的教材挺多的,就想收集一下备用,但是一个个的下载实在太麻烦了,于是想起来利用Python应该能实现批量下载的。于是乎动手操作,先查资料。下载地址:https://bp.pep.com.cn/jc/
首先感谢—zhiang张的文章: https://blog.youkuaiyun.com/jonathanzh/article/details/78630587
经过简单的修改,实现了下载功能。
下面是第一次完成的代码,可以实现下载功能:

import urllib.request
import re
import os

# open the url and read
def getHtml(url):
    page = urllib.request.urlopen(url)
    html = page.read()
    page.close()
    return html

def getUrl(html):
    # 此处reg是利用正则表达式获取含有'.pdf'的链接
    reg = 'href="(.*\w\.pdf)"'
    url_re = re.compile(reg)
    url_lst = url_re.findall(html.decode('UTF-8'))
    return(url_lst)

def getFile(url):
    file_name = url.split('/')[-1]
    u = urllib.request.urlopen(url)
    f = open(file_name, 'wb')

    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        f.write(buffer)
    f.close()
    print ("Sucessful to download" + " " + file_name)


root_url = 'http://bp.pep.com.cn/jc/yjcz'  #下载地址中相同的部分

html = getHtml(raw_url)
url_lst = getUrl(html)

if not os.path.exists('pdf_download') : #文件夹不存在时,再进行创建
    os.mkdir('pdf_download')
os.chdir(os.path.join(os.getcwd(), 'pdf_download'))

for url0 in url_lst[:]:
    url = re.sub('\A\.', '', url0)
    url = root_url + url  # 形成完整的下载地址
    getFile(url)

虽然相面的代码可以运行,但是获得的文件是”P020200210116270366430.pdf“这种命名方式,如果手动重命名文件也比较麻烦,因此先通过抓取课本名称,然后再给文件重命名的方式对文件进行处理。
修改后的代码如下:

from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
import os

# open the url and read
def getHtml(url):
    page = urlopen(url)
    html = page.read()
    page.close()
    return html


def getUrl(html):
    reg = 'href="(.*\w\.pdf)"'
    url_re = re.compile(reg)
    url_lst = url_re.findall(html.decode('UTF-8'))
    return(url_lst)


def getFile(url,i):
    file_name = url.split('/')[-1]
    u = urlopen(url)
    f = open(file_name, 'wb')

    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break
        f.write(buffer)
    f.close()
    print("Sucessful to download" + " " + file_name)
    # 新增重命名操作
    title = title_lst[i]
    dir1 = 'F:\\DOC\\Project\\2020\\pdf_download0\\' + file_name
    dir2 = 'F:\\DOC\\Project\\2020\\pdf_download0\\' + title.get_text() + '.pdf'
    if os.path.exists(dir1):
        os.rename(dir1, dir2)
    # os.rename(file_name, title)
    print ("下载成功:" + " " + title.get_text() + '.pdf')


root_url = 'http://bp.pep.com.cn/jc/yjcz'  #下载地址中相同的部分

html = getHtml(raw_url)
url_lst = getUrl(html)

file_url = urlopen(root_url)
bsobj = BeautifulSoup(file_url, 'lxml')
title_lst = bsobj.findAll({"h6"})

if not os.path.exists('pdf_download0') : #文件夹不存在时,再进行创建
    os.mkdir('pdf_download0')
os.chdir(os.path.join(os.getcwd(), 'pdf_download0'))

for i in range(len(title_lst)):
    url = re.sub('\A\.', '', url_lst[i])
    url = root_url + url  # 形成完整的下载地址
    getFile(url, i)

为了获取课本名称引入了BeautifulSoup,比较冗余……
其实这里通过正则表达式应该也可以获取到课本名称的,不过试了几次没成功,所以改用了finaAll()函数来实现这个功能。
通过各种学习,有增加了一些爬虫应该有的内容,优化了一些冗余的部分,又形成了第三个版本……当然还是不够完美……还有可以优化的地方,还请大神们多指教。
第三版代码如下:

from bs4 import BeautifulSoup
from urllib.request import urlopen, Request
import re
import os
import time
from fake_useragent import UserAgent

# 获取下载地址和文件名称
def getUrl(url_head):
    ua = UserAgent()
    # 请求头
    headers = {"User-Agent": ua.random}
    # 请求网址
    response = Request(url=url_head, headers=headers)
    print(response.headers)

    html = urlopen(response)
    print('html:', html)
    bsobj = BeautifulSoup(html, 'lxml')
    url_list = bsobj.findAll(name='a', attrs={"href": re.compile('.pdf$')})
    title_list = bsobj.findAll({"h6"})
    return url_list,  title_list

def getFile(url, one_name):
    file_name = url.split('/')[-1]
    u = urlopen(url)
    f = open(file_name, 'wb')

    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break
        f.write(buffer)
    f.close()
    print("原文件下载成功:" + " " + file_name)
    # 新增重命名操作
    dir1 = file_path + file_name  # 优化了文件路径
    dir2 = file_path + one_name + '.pdf'
    if os.path.exists(dir1):
        os.rename(dir1, dir2)
    elif os.path.exists(dir2):
        print('%s 文件已存在!' % dir2)
    else:
        print('%s 下载失败!' % dir1)
    # os.rename(file_name, title)
    print("下载成功:" + " " + one_name + '.pdf')
    time.sleep(30)

if __name__ == '__main__':
    # 下载地址中相同的部分
    root_url = 'http://bp.pep.com.cn/jc/yjcz'  # 义务教育初中教材下载地址
    # root_url = 'http://bp.pep.com.cn/jc/ptgzjks'  # 普通高中教材下载地址
    file_path = 'F:\\DOC\\Project\\2020\\pdf_download0\\'
    print('文件保存地址:', file_path)

    if not os.path.exists(file_path):  # 文件夹不存在时,再进行创建
        os.mkdir(file_path)
        print('文件夹 %s 新建成功!' % file_path)
    os.chdir(os.path.join(os.getcwd(), file_path))
    url_lst, title_lst = getUrl(root_url)
    print('获取地址和文件名成功!')
    print('准备开始下载文件!')
    for i in range(len(title_lst)):
        url = re.sub('\A\.', '', url_lst[i].get('href')) # 获得的下载地址是'./'开头的,需要进行修剪
        url = root_url + url  # 形成完整的下载地址
        title = title_lst[i].get_text()
        print('下载地址:', url)
        getFile(url, title)
        print('**********开始下一循环**********')
    print('全部文件下载完成!')

至此经过两天的摸索和修改,终于能够实现最初的目的了。
由于没全面的学习爬虫知识,因此踩了几个坑,特别是正则表达式写不好,获取不到想要的内容。对于以上代码肯定还存在很多可以优化的地方,还请大神们多指教!

小白,写第一篇文章,还是比较忐忑的……
希望能对各位学习者有所帮助,在优快云里共同进步!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值