通过爬取内容部分实现了将小说单章内容下载到本地,通过爬取章节目录部分得到了小说章节名称和完整链接。要下载整部小说,只要将两部分合起来即可。
考虑到爬取时间有点长,再加上一行信息充当进度条。
完整代码如下
import requests
from bs4 import BeautifulSoup
# 获取章节名称和链接
target = 'https://www.52bqg.com/book_12525/' # 目录页地址
req = requests.get(url = target)
req.encoding = req.apparent_encoding # 编码转换
# 使用beautifulsoup 筛选出id=list的div标签
bf = BeautifulSoup(req.text,"html.parser")
lists = bf.find_all('div',id='list')
lists = lists[0]
# 再次使用bs,从lists中筛选出所有的标签a
bf_a = BeautifulSoup(str(lists), 'html.parser') # 不加str()会报错
a = bf_a.find_all('a')
titles = [] # 存放章节名称
urls = [] # 存放章节链接
for s in a:
titles.append(s.string)
urls.append(target + s.get('href')) # 完整链接
print('开始下载……')
# 使用for循环爬取内容
for i in range(len(urls)):
title = titles[i] # 标题
url = urls[i] # 内容页地址
req = requests.get(url = url)
req.encoding = req.apparent_encoding # 编码转换
# 使用beautifulsoup 筛选出id=content的div标签
bf = BeautifulSoup(req.text,"html.parser")
content = bf.find_all('div',id='content')
content = content[0].text
# 内容优化
content = content.replace('\r\n 一秒记住【笔趣阁 www.52bqg.com】,精彩小说无弹窗免费阅读!\r\n \xa0\xa0', '')
content = content.replace('\r\n\xa0\xa0','') # 去空行和段首空格,保留\n实现换行,保留2个空格使首行缩进2空格
content = '\n' + title + '\n' + content # 保存的内容加上章节名称
# 保存到本地
file = open('卡徒.txt','a', encoding='utf-8') # 以追加模式,在当前目录下创建并写入,采用utf-8编码
file.write(content)
file.close()
# 进度条
print('%3d , %s ,已下载%.1f%%'%(i+1,title, i/len(titles)*100))
print('下载完毕!')
运行程序,开始很顺利,但不久就卡住了,不报错,也不往下继续运行。
又多次重新程序,每次卡住的位置都不一样,很随机,偶尔也能够下载成功。这样看来程序没有问题,极有可能与网络或者网站有关啦。
req = requests.get(url = url)
应该是这句,向服务器的请求不能得到及时回应,然后就陷于假死状态。那就给彵加上一个回应时间看看。
req = requests.get(url=url, timeout=3) # 相应时间为3秒
运行程序,很快程序报错
大体意思应该是响应超时,之前的问题肯定也与这个有关。
此时将for循环中起始数改为最后的下载数字。
如上面最后的下载数是4,可将for循环从原来的
for i in range(len(urls)):
改为
for i in range(4,len(urls)):
重新运行程序,还可以继续下载,如果又出现问题,那就继续改起始数,这也算是手动模式了。
现在程序可以说处于手动状态,运行程序时需要人在电脑前手动配合,这显然不是我们想要的结果。
解决的思路是,当程序出现超时错误时,程序能够再次发送请求,直到获得服务器响应为止。
想到的方法是:while + try……except……
修改后的代码如下:
import requests
from bs4 import BeautifulSoup
# 获取章节名称和链接
target = 'https://www.52bqg.com/book_12525/' # 目录页地址
req = requests.get(url = target)
req.encoding = req.apparent_encoding # 编码转换
# 使用beautifulsoup 筛选出id=list的div标签
bf = BeautifulSoup(req.text,"html.parser")
lists = bf.find_all('div',id='list')
lists = lists[0]
# 再次使用bs,从lists中筛选出所有的标签a
bf_a = BeautifulSoup(str(lists), 'html.parser') # 不加str()会报错
a = bf_a.find_all('a')
titles = [] # 存放章节名称
urls = [] # 存放章节链接
for s in a:
titles.append(s.string)
urls.append(target + s.get('href')) # 完整链接
print('开始下载……')
i = 0
while i <= len(urls):
title = titles[i] # 标题
url = urls[i] # 内容页地址
try:
req = requests.get(url=url, timeout=3) # 相应时间为3秒
except:
print('========响应时间过长,重新下载!========')
req = requests.get(url=url, timeout=3) # 相应时间为3秒
req.encoding = req.apparent_encoding # 编码转换
# 使用beautifulsoup 筛选出id=content的div标签
bf = BeautifulSoup(req.text,"html.parser")
content = bf.find_all('div',id='content')
content = content[0].text
# 内容优化
content = content.replace('\r\n 一秒记住【笔趣阁 www.52bqg.com】,精彩小说无弹窗免费阅读!\r\n \xa0\xa0', '')
content = content.replace('\r\n\xa0\xa0','') # 去空行和段首空格,保留\n实现换行,保留2个空格使首行缩进2空格
content = '\n' + title + '\n' + content # 保存的内容加上章节名称
# 保存到本地
file = open('卡徒.txt','a', encoding='utf-8') # 以追加模式,在当前目录下创建并写入,采用utf-8编码
file.write(content)
file.close()
# 进度条
print('%3d , %s ,已下载%.1f%%'%(i+1,title, i/len(titles)*100))
i = i + 1
print('下载完毕!')
运行程序,验证一下。
可以看到,当响应时间过长时,会尝试再次请求服务器,保证程序继续运行!!!
至此,在笔趣阁自动下载整部小说的功能算是实验成功!!