此代码实现了通过输入作者名查找小说,列出相似作者的小说,通过用户自行选择小说名下载,亦实现了通过输入小说名字查找小说。相关代码已上传至github:https://github.com/qazhw/paFeiLuXS
使用工具
python3 ,BeautifulSoup库,requests库
网页分析
随便找一本小说
以此为例
我们发现所有章节都存放在class="DivTd"的div便签中,这里我直接提取的div标签,
效果如下:
[<div class="DivTd">
<a href="//b.faloo.com/965864_1.html" target="_self" title="洪荒:诸天打手群,开局平定黑暗动乱!:第1章 诸天万界打手群">第1章 诸天万界打手群</a>
</div>, <div class="DivTd">
<a href="//b.faloo.com/965864_2.html" target="_self" title="洪荒:诸天打手群,开局平定黑暗动乱!:第2章 邀请十位洪荒大能入群">第2章 邀请十位洪荒大能入群</a>
</div>, <div class="DivTd">
<a href="//b.faloo.com/965864_3.html" target="_self" title="洪荒:诸天打手群,开局平定黑暗动乱!:第3章 来自北斗世界叶黑的四星任务">第3章 来自北斗世界叶黑的四星任务</a>
</div>, ···]
再通过遍历这个列表来提取出a标签的字符串文本和href
naurl = {} # 在for循环里建一个空字典 实现列表嵌套多个字典 形式上面给出
naurl['章节名'] = i.a.string # 获取a标签的章节名
naurl['章节链接'] = servers + i.a.get('href') # 获取a标签的内容
爬虫实现
一、获取章节名、章节链接
直接用beautifulsoup的 find_all() 方法获取a标签 相关注释已在程序给出
def get_download_url(target):
print(target) # 输出返回的链接
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36 Edg/91.0.864.53'
}
req = requests.get(url=target, headers=headers)
html = req.text # 获取页面html文本
bf = BeautifulSoup(html, "lxml") # 解析html
print('-----------------------')
# print(bf)
alist = bf.find_all('a', class_='c_con_li_detail') # 匹配
print(alist)
if not alist:
alist = bf.find_all('div', attrs={'class': 'DivTd'})
print(alist)
l = []
# print(html)
book_name = bf.find('h1') # 获取 h1 小说名字
# 异常 搜索小说 若小说不存在则返回异常输出异常信息 ,反之小说存在则显示搜索成功
try:
book_name = book_name.getText() # 请求url 获取响应文本
if book_name:
print('小说已搜索成功') # 若book_name成功获取文本,则输出搜索成功
print(book_name)
except Exception as e:
print('小说不存在')
print(e)
sys.exit()
finally:
time.sleep(2)
book_name = book_name.strip("\r\n目录") # 书名去除首尾换行符
# book_name = book_name.replace("\n", "--") # 将标题内的换行符以--代替
# 如果磁盘中存在book_name(书名)文件夹,则不创建,如果不存在,则创建{书名}文件夹
if not os.path.exists(book_name):
os.makedirs(book_name)
print(f'《{book_name}》开始下载:')
k = int(input("请输入要下载的章节数"))
for i in len(alist[:k]):
print(i)
naurl = {}
# 异常 目录存在空章节 剔除掉
try:
naurl['章节名'] = i.a.string
naurl['章节链接'] = servers + i.a.get('href')
l.append(naurl)
except Exception as e:
print(e)
del alist[i]
k-=1
# naurl['章节名'] = i.a.string
# naurl['章节链接'] = servers + i.a.get('href')
print('ddd***************************', l)
for j in tqdm(range(k), bar_format='{l_bar}%s{bar}%s{r_bar}' % (Fore.LIGHTGREEN_EX, Fore.RESET)):
# print(l[i]['章节链接'])
wjm = str(j + 1) + '- ' + l[j]['章节名'] #文件名称
wjm=re.sub('(\d/\d)','',wjm) # 删掉(1/2)等不合法命名字符
writer(wjm, book_name, get_contents(l[j]['章节链接']))
return book_name
二、获取章节内容
获取文章内容不用多说,就这点东西
- 请求链接页面
- 返回内容
- 创建bs对象,lxml解析
- 利用find_all提取class为nove······的div标签,返回结果为列表
- 去除多余字符
def get_contents(target):
req = requests.get(url=target) # 请求每一章页面
html = req.text # 获取html文本
# print(html)
bf = BeautifulSoup(html, "lxml") # lxml解析 创建bs对象
texts = bf.find_all('div', class_='noveContent') # 获取小说文本内容
texts = texts[0].text.replace('\u3000' * 2, '\n\n') # 去除全角空白符
# print(texts)
return texts # 返回文本
三、写入文件
def writer(name, path, text):
savePath = path + "\\" + str(name) + ".txt" # 文件命名 路径为path
with open(savePath, 'a+', encoding='utf-8') as f:
f.write(name.center(50) + '\n')
print('正在下载' +name)
f.writelines(text) # 每写完一次加个换行
f.write('\n\n')
程序执行过程效果图:
另外我加了弹窗功能 ,下载完毕就会通知
toaster = ToastNotifier()
toaster.show_toast("爬取完毕",
k,
icon_path="D:/suiji/image.ico",
duration=10)