requests,parsel,以及你的目标小说
本次文章的要求较简单,只是你想看的小说,爬取它的内容,并保存为txt文档,达到这个功能只需15行代码即可
爬取一个网文的内容,是我们的目的,此前,我们可以设想这个程序最终的样子,它并不用于商业化。它应该是简单的,不复杂的,易上手的,应该有可视化的执行界面,可以一键创建txt小说文件,可以读取所有章节内容,有进度,可以显示失败与否,能有多个网站的资源,有搜索栏。
两个库,还有一个是小说目录网址在这个地方可以看到小说的所有章节以及小说名字
还有一个就是小说网站的网址,这个是因为该网站的href属性做的调整
import requests import parsel url = 'https://www.81zw.com/book/42186/' burl = 'https://www.81zw.com'
此处需要配合网页源代码使用,有五个必要的操作,这五个的使用贯穿了这个程序。
requests.get() parsel.Selector() .css().get() '\n'.join() with open()
接下来一一讲解
在你使用了准备好上述条件后,小说名字。
page = requests.get() selector = parsel.Selector(page.text) novel_name = selector.css('#info h1::text').get
接下来打印novel_name就是小说名字
request.get()获取它的网页源代码,.text可以使它字符串输出,但我们并不是要一整个网页。我们需要的只是它的名字,为了这个目的,我们就要使用css选择,
通过parsel.Selector然后使用css选择固定的东西,这里就涉及指定的网页内容,这里并不是一成不变('#info h1::text'),此处不懂请跳转至4.1
这里如果打印novel_name得到的就是小说名字,然后我们还需要小说的每个章节名,我们是全部输出在一个txt文件中,所以在文章正文网页中查看更方便些。
所以为css('.bookname h1::text').get()
看到这里并了解网页的检查操作的话你应该已经懂大体的操作了(如果不懂请看第四),接下来用for循环所有章节并使得到的文字注入txt文件中
如何循环所有的章节呢,简单来说就是要打开每一个章节并读取正文记录,你要观察网址之间的规律在那里
这是官网www.81zw.com 八一中文网
这是小说页面://www.81zw.com/book/42186/ 我师兄实在是太稳健了
这是小说的第一章www.81zw.com/book/42186/18304635.html 小小灵娥
小说的第二章呢,www.81zw.com/book/42186/18304636.html 师兄的入门审核
第三章呢,你可以猜一下了,如你所想是18304637结尾 入门第一课
这里你可能就以为贯穿所有了,但其实这个是错误的,你可以观察后续的网址代码,会发现有变化,但也有其他方法也很简单,关键就在于
ls = goal.css('#list a::attr(href)').getall()
这个是什么意思呢?他是个列表,涵盖了所有的网址代码(见4)每个元素都是这样的形式/book/42186/18304635.html,这样做一些灵活变化
所以应该
for i in ls: url = 'https://www.81zw.com/' + i # 然后在这个循环下再对url这个网址操作,他会循环遍历每一个章节
然后套用上面的函数,一样的内核
x = requests.get(url) y = parsel.Selector.(x.text) z = y.css('#content::text').get
然后就是有新意的地方了。
with open(文件名称, 方式, 编码方式) as f:
文件名称要有后缀,编码方式一般使用'utf-8',然后对着f使用write写入小说内容
r |
以读方式打开文件,可读取文件信息。 |
w |
以写方式打开文件,可向文件写入信息。如文件存在,则清空该文件,再写入新内容 |
a |
以追加模式打开文件(即一打开文件,文件指针自动移到文件末尾),如果文件不存在则创建 |
with open('novel_name' + '.txt', 'a', encoding='utf-8') as f: f.write(content)
到这里接近尾声,其他打印章节名,空行之类的操作可以自行选择
对你需要的小说网页目录页选择检查网页源代码然后应该是这样的形式
使用按键选中可以指定到某个目标,我使用的是edge,左上角那个标志就是这个功能。然后我选中了小说名字,id = info,在h1标签下。
他是有规律的,上面的是小说名字,所以应该是css('#info h1::text')
这个是章节名字,所以是css('#list a::text'),他的后续网址是css('#list a::attr(href)')
前者的内容是第一张小小灵娥,后者是橘色内容/book/42186/18304635.html
这里我打开了正文的第一章,这里是正文的位置在content下,此外每个网站可能都有所不同,如果不是id而是class就需要用.来开头而不是#
所以正文的部分就是css('#content::text')
需要getall,否则你只会得到一句。
import requests import parsel url = 'https://www.81zw.com/book/42186/' url1 = 'https://www.81zw.com/' goal = parsel.Selector(requests.get(url).text) novel_name = goal.css('#info h1::text').get() ls = goal.css('#list a::attr(href)').getall() print(ls) for link in ls: url2 = 'https://www.81zw.com' + link goal1 = parsel.Selector(requests.get(url2).text) novel = goal1.css('#content::text').getall() name = goal1.css('.bookname h1::text').get() cc = '\n'.join(novel) with open('w' + '.txt', 'a', encoding='utf-8') as f: f.write(name) print() f.write(cc) print()
这个是整个代码,如果不出意外运行该文件后应该会在该文件所在的目录里创建一个
我的运行时间是960s,运行时间使用time模块后续再说明
如果有任何疑问,欢迎在评论区询问,我会耐心解答