vlambda博客
学习文章列表

开源用于下载网页上的文件的python爬虫


        在2020的出现疫情期间,学生们都不能去学校上课,然后看到有个公号上说在网站上把教材发布了出来供大家看,当时去看了一下,感觉有好多,如果手动下载可能要下很长时间。一时懒惰劲上来了,然后就在网上搜了一 段代码自己改了一下,一边改一边测试,最终把那个网站发布的教材全部下载下来了。但是从小学到高中所有年级都只有半学期的教材,因为下半学期疫情好些了,就没太关注有没有再放教材出来,所以下就没有下载到!不过这代码可以用于初学爬虫。把代码发出来一是为了避免太久后找不到,也可以给想学爬虫的初学者一个参考吧。

        下面代码里的网站已经关闭了相关页面,也就是说下载不了了,可以用其他能下载文件的网站自己改改试试。里面被#注释掉的是当时测试时的想法和尝试,所以如果要下载其他网站上的文件(前提是网站没有做反爬措施)也基本可以这样一步步的测试直到实现目的。代码有点乱,将就看吧!懒惰劲又上来了!

#!/usr/bin/env python# -*- coding: utf-8 -*-"""@author: Kingchen#当时测试的版本好像是Python3.5+download_web_file.py
"""import requests,sys,webbrowser,bs4,osfrom bs4 import BeautifulSoupimport urllib.request


"""soup = BeautifulSoup(html, 'http://bp.pep.com.cn/jc/')for h5 in soup.select('h5'): print('获取:', h5.string)    这里面注释的内容是刚开始的时候用于测试那个网站的h5标签里面的内容"""#下面是主程序def start_main():    url = 'http://bp.pep.com.cn/jc/' #用变量接受要下载文件的网址 res = requests.get('http://bp.pep.com.cn/jc/')#用requests的get方法获得要下载文件的网址网页的内容 #print(res) #print(res.raise_for_status()) res.encoding='utf-8' #这样能解决获取到的网页中文内容乱码的问题 soup = bs4.BeautifulSoup(res.text,"lxml") #print("This is soup:" + str(soup)) #linkElems = soup.select('.list_sjzl_jcdzs2020 a')#整个网页以条件'.list_sjzl_jcdzs2020 a'读取为一个列表 linkElems = soup.select('li a')#整个网页以条件'f1 a'读取为一个列表 print('列表总数:',len(linkElems)) #print('获取a txt:', linkElems)#输出列表里是整个页面符合'.list_sjzl_jcdzs2020 a'要求的内容 #print('获取a txt:', linkElems.string)#AttributeError: 'list' object has no attribute 'string' #linkElems1 = soup.select('.list_sjzl_jcdzs2020 h5') #print('获取H5 txt:', linkElems1.string) """ l = linkElems.encode('utf-8') print(l) #AttributeError: 'list' object has no attribute 'encode' """ ''' 内建的 Python 函数 min()返回传入的整型或浮点型参数中最小的一个, 用户查询的主题可能少于 5 个查询结果。soup.select()调用返回一个列表,包 含匹配'.r a'选择器的所有元素,所以打开选项卡的数目要么是 5,要么是这个列表的 长度(取决于哪一个更小)。(也有内 建的 max()函数,返回传入的参数中最大的一个)。你可以使用 min()弄清楚该列表 中是否少于 5 个链接,并且将要打开的链接数保存在变量 numOpen 中。然后可以 调用 range(numOpen),执行一个 for 循环。 在该循环的每次迭代中,你使用 webbrowser.open(),在 Web 浏览器中打开一个 新的选项卡。请注意,返回的<a>元素的 href 属性中,不包含初始的 http://google.com 部分,所以必须连接它和 href 属性的字符串。 ''' ''' numOpen = min(5,len(linkElems))#在新的选项卡中打开前 5 个查询结果————5个下级页面 for i in range(numOpen): # webbrowser.open('http://bp.pep.com.cn/jc/' + linkElems[i].get('href')) ''' saveFilePath = 'F:\\download\\' #numlE = max(2,len(linkElems))#在新的选项卡中打开所有下级页面 numlE = max(2,len(linkElems))#在新的选项卡中打开所有下级页面 #print(numOpen) num = 0 #num1 = 0 for i in range(numlE): #可打开能下载文件那一页 #webbrowser.open('http://bp.pep.com.cn/jc/' + linkElems[i].get('href')) #print('i 的值是:',i) #num = num + 1 #一共有118个分类 #print(num)#这里是用来测试用的,主要是看一下有多少个文件,因为每一页对应一个文件
leText = linkElems[i].getText()#取得用于目录的文本 hrefText = linkElems[i].get('href') print('第一个文本是:' + leText +';'+ 'href是:' + hrefText) url_raw = url + hrefText[2:]#获得下一级页面的网址 #print('第二级的url是:',url_raw) res1 = requests.get(url_raw) res1.encoding='utf-8' #这样能解决获取到的网页中文内容乱码的问题 soup1 = bs4.BeautifulSoup(res1.text,"lxml") pdflinkElems = soup1.select('a[href$="pdf"]') #print('pdflinkElems:',pdflinkElems) linkElems1 = soup1.select('li[class$="f1"]') #titleTextSoup = bs4.BeautifulSoup(res1.text,"lxml") # linkElems2 = soup1.select('h6 a') # titleText = linkElems2[0].getText()#取得用于目录的文本 #print('第2级页面以"li a"选择的列表是:',linkElems1) num1 = 0 # numSave = max(2,len(linkElems1)) numSave = len(pdflinkElems) #print('numSave:',numSave) for j in range(numSave): #webbrowser.open('http://bp.pep.com.cn/jc/' + linkElems1[j].get('href')) num1 = num1 + 1 #一共有118个分类 #print('第2级目录数量是:',num1) # leText1 = linkElems1[0].getText()#取得用于目录的文本 # print('第二级页面里的文本:',leText1) linkElems2 = soup1.select('h6 a') titleText = linkElems2[j].getText()#取得用于目录的文本 print('书名文本是:', titleText) # pdflinkElems = soup1.select('a[href$="pdf"]')#用于取得PDF文件的链接 hrefpdflink = pdflinkElems[j].get('href') #print('hrefpdflink:',hrefpdflink) url_raw1 = url_raw + hrefpdflink[2:]#获得下一级页面的网址 print('pdf文件下载地址:',url_raw1) # print(url_raw1 + linkElems1[j])#.get('href')) #r = requests.get(url_raw1) downloadPdf = requests.get(url_raw1) try: downloadPdf.raise_for_status() except Exception as exc: print('下载遇到问题1:%s' %(exc)) #print('预览PDF文件名:',downloadPdf) filename = titleText + '.' + url_raw1.split('.')[-1] print('filename is:',filename) if downloadPdf.status_code != 200: print('下载异常!') #return try: with open(filename, 'wb') as f: #req.content为获取html的内容 f.write(downloadPdf.content) print('下载成功!') except Exception as e: print('下载遇到问题2:%s' %(e)) if __name__ == '__main__': start_main()