于是我就写了一个简单的爬虫提供根据卷、章下载小说,并且可以自动爬取所有插图的脚本
食用方法:
先打开该轻小说网站,由于搜索功能需要登录,所以还请麻烦登录/注册一下
网站关闭通知我认为是个摆设,因为这个网站依然在正常运作,并且我在看的连载小说也在更新中!
大家可以无视该通知,直接注册、登录!
然后通过搜索等方法打开某一个小说详情页
此时你的链接将会是这样:
https://www.wenku8.net/book/[小说ID].htm
但这还不够,由于我多次测试发现目录链接中有一个参数并不固定所以还请进一步获取该参数,才能继续下载
点击 “小说目录” 链接,
你将会跳转到小说目录页,此时就可以将链接里:
https://www.wenku8.net/novel/[这一部分]/index.htm
中的那一部分填入 Python 脚本最开始要求输入的内容了下载使用多线程,不太清楚这个特性在 Python 几出来的,但我测试使用的是 Python 3.10 版本
已知 Python 3.12 版本有个不明为何的特性导致多线程创建失败,所以请使用低于 Python 3.12 版本的 Python
程序运行结束即为小说下载完成,可以翻看一下输出日志有没有报错,如果有无法解决的错误欢迎反馈!
只是一个简单的爬虫程序,有哪里写的不好的欢迎大家指正,谢谢!
import os
import time
from threading import Thread
import requests
from bs4 import BeautifulSoup
print("""轻小说文库下载器 (www.wenku8.net) -By NekoW
仅供爬虫原理学习如有侵权请联系删除。""")
book = input("请输入小说 ID: ")
retry_time = 5
# 替换内容,可填入三个参数:原内容,替换内容(默认为空),替换次数(默认-1)
# 例如: ['测试1', '测试2'] 就是将所有 '测试1' 替换为 '测试2'
# 如果只替换一次则为: ['测试1', '测试2', 1]
# 如果想要替换为空,则可以省略第二个参数,
# 例如只替换一次 '测试1' 为空: ['测试1', 1]
replaces = [
[u'\xa0'],
['本文来自 轻小说文库(http://www.wenku8.com)\r\n'],
['本文来自 轻小说文库(http://www.wenku8.com)'],
['最新最全的日本动漫轻小说 轻小说文库(http://www.wenku8.com) 为你一网打尽!'],
['\n\r\n', '\n\n'],
['\n', 1],
['\r\n\n', 1],
['\n\n\n', 1]
]
invalid_filename = ['\\', '/', ':', '*', '?', '"', '<', '>', '|']
novel_url = "https://www.wenku8.net/novel/%s/" % book
url = '%s/index.htm' % novel_url
headers = {
'Accept-Encoding': 'gzip, deflate, br',
'Accept': 'text/html,application/xhtml+xml,application',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
}
request = requests.get(url, headers=headers)
text = request.text.encode(request.encoding, 'ignore')
soup = BeautifulSoup(text, 'html.parser')
novel_title = soup.find('div', attrs={'id': 'title'}).text.strip()
try:
os.mkdir(path=novel_title)
except FileExistsError:
pass
table = soup.find('table', attrs={'class': 'css'})
trs = table.find_all('tr')
group = None
novels = {}
for tr in trs:
tds = tr.find_all('td')
if len(tds) == 1:
group = tds[0].text.strip()
novels[group] = []
continue
for td in tds:
if td.find('a') is None:
continue
link = td.find('a')['href']
title = td.text.strip()
novels[group].append({'title': title, 'link': link})
def download_image(_image, _group, _chapter):
def helper():
filename = _image['src'].split('/')[-1]
print('正在保存图片 %s 到 %s/%s' % (filename, _group, _chapter['title']))
try:
_request = requests.get(_image['src'], headers=headers)
with open('%s/%s/%s/%s' % (novel_title, _group, _chapter['title'], filename), 'x+b') as f:
f.write(_request.content)
print('文件已保存至 %s/%s/%s/%s!' % (novel_title, _group, _chapter['title'], filename))
except Exception as e:
if type(e) is FileExistsError:
return
print('保存图片 %s 时发生错误: %s, 正在重试...' % (filename, str(e)))
time.sleep(retry_time)
helper()
helper()
def download_novel(_group, _chapter):
def helper():
try:
print('正在下载 %s 的 %s...' % (_group, _chapter['title']))
_request = requests.get(novel_url + _chapter['link'], headers=headers)
_text = _request.text.encode(_request.encoding, 'ignore')
_soup = BeautifulSoup(_text, 'html.parser')
content = _soup.find('div', attrs={'id': 'content'})
images = content.find_all('img')
if len(images) > 0:
print('在章节 %s 中找到 %d 个图片' % (_chapter['title'], len(images)))
try:
os.makedirs('%s/%s/%s' % (novel_title, _group, _chapter['title']))
except FileExistsError:
pass
for image in images:
image_thread = Thread(target=download_image, args=(image, _group, _chapter))
image_thread.start()
_text = content.text
for replace in replaces:
arguments = [replace[0]]
if len(replace) > 1:
if type(replace[1]) is int:
arguments.append('')
arguments.append(replace[1])
else:
arguments.append('')
if len(replace) > 2:
arguments.append(replace[2])
else:
arguments.append(-1)
_text = _text.replace(arguments[0], arguments[1], arguments[2])
try:
os.makedirs('%s/%s' % (novel_title, _group))
except FileExistsError:
pass
if _text == '':
return
cp_title = _chapter['title']
for s in invalid_filename:
cp_title = cp_title.replace(s, '')
filename = f"{_group}/{cp_title}.txt"
with open(f'{novel_title}/{filename}', 'x+', encoding='utf-8') as f:
f.write(_text)
print('文件已保存至 %s/%s!' % (novel_title, filename))
except Exception as e:
if type(e) is FileExistsError:
return
print("下载 %s %s 时发生错误: %s, 正在重试..." % (_group, _chapter['title'], str(e)))
time.sleep(retry_time)
helper()
helper()
for group, novel_list in novels.items():
for chapter in novel_list:
Thread(target=download_novel, args=(group, chapter)).start()