上次爬取200多章节的《天才基本法》因为没有多线程耗时5分钟才能下载完,决定学习多线程的相关内容,终于成功了,再次下载10秒钟就OK。现在换一部小说《少年派2》,介绍下多线程下载。
首先还是写一个根据网址获取html源码的通用函数,下载目录和每个章节都要调用它。这个函数是通用的,直接复制就行,无需修改。
import requestsfrom bs4 import BeautifulSoupimport threadingdef 获取网页源码(url): headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36" } try: 网址请求 = requests.get(url=url, headers=headers) 网址请求.raise_for_status() 网址请求.encoding = 网址请求.apparent_encoding return 网址请求.text # 返回网页源码 except: print('网页地址访问失败') return '获取失败'
下载目录,除了网址,其余和上次一样。
# 开始爬取目录目录地址 = 'https://www.xxxx.com/book/shaonianpai2.html'目录源码 = 获取网页源码(目录地址)章节地址和名称列表 = []源码解析器 = BeautifulSoup(目录源码, 'lxml')目录代码 = 源码解析器.select('div > ul> li') # 层级选择for 章节 in 目录代码: if 章节.text == '': continue 章节地址 = 章节.find('a').attrs['href'] 章节名称 = 章节.a.string 章节地址和名称列表.append([章节地址, 章节名称])print('章节列表下载成功!')
不一样的是,每个章节的下载都放到一个函数里,供后面的线程代码调用。由于每个线程结束的时间不同,下载好的章节内容不能用列表,改用字典存储。
def 下载并解析某章节(章节地址, 章节名称): print(章节名称 ' 开始下载。。。') 章节源码 = 获取网页源码(章节地址) 章节源码解析器 = BeautifulSoup(章节源码, 'lxml') 本章内容代码 = 章节源码解析器.find('div', id='htmlContent') 本章内容代码转文本 = str(本章内容代码) 本章内容代码转文本 = 本章内容代码转文本.replace("<br/><br/>", "n") 章节源码解析器 = BeautifulSoup(本章内容代码转文本, 'lxml') 本章内容代码 = 章节源码解析器.find('div', id='htmlContent') 本章内容文本 = 本章内容代码.text 章节内容字典[章节名称] = 本章内容文本
多线程下载:把每个章节的下载放入线程列表,设置主线程等待它们结束
# 多线程下载章节内容章节内容字典 = {}线程列表 = []for 章节 in 章节地址和名称列表: 章节地址 = 章节[0] 章节名称 = 章节[1] 子线程 = threading.Thread(target=下载并解析某章节, args=(章节地址, 章节名称)) 线程列表.append(子线程)for 子线程 in 线程列表: 子线程.setDaemon(True) # 设置为守护线程,主线程可以等待 子线程.start()for 子线程 in 线程列表: 子线程.join()
最后根据章节顺序合并成一个文本文件。
# 保存到文件电子书文件 = open('少年派2.txt', 'a', encoding="utf-8")for 章节 in 章节地址和名称列表: 章节地址 = 章节[0] 章节名称 = 章节[1] 电子书文件.write(章节名称 章节内容字典[章节名称] "nn")电子书文件.close()print('大功告成!')
不会下载的可以评论区留下邮箱,我把文件发给你。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如有侵权行为,请第一时间联系我们修改或删除,多谢。