开源用于下载网页上的文件的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 = 0for 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('下载异常!')#returntry: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()
