开源用于下载网页上的文件的python爬虫
在2020的出现疫情期间,学生们都不能去学校上课,然后看到有个公号上说在网站上把教材发布了出来供大家看,当时去看了一下,感觉有好多,如果手动下载可能要下很长时间。一时懒惰劲上来了,然后就在网上搜了一 段代码自己改了一下,一边改一边测试,最终把那个网站发布的教材全部下载下来了。但是从小学到高中所有年级都只有半学期的教材,因为下半学期疫情好些了,就没太关注有没有再放教材出来,所以下就没有下载到!不过这代码可以用于初学爬虫。把代码发出来一是为了避免太久后找不到,也可以给想学爬虫的初学者一个参考吧。
下面代码里的网站已经关闭了相关页面,也就是说下载不了了,可以用其他能下载文件的网站自己改改试试。里面被#注释掉的是当时测试时的想法和尝试,所以如果要下载其他网站上的文件(前提是网站没有做反爬措施)也基本可以这样一步步的测试直到实现目的。代码有点乱,将就看吧!懒惰劲又上来了!
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@author: Kingchen
#当时测试的版本好像是Python3.5+
download_web_file.py
"""
import requests,sys,webbrowser,bs4,os
from bs4 import BeautifulSoup
import 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()