Python爬虫练习笔记——爬取一本小说并保存为txt文件

news/2024/11/24 4:27:11/

最近竟然开始磕起了黄晓明和尹正的CP!!!
但是万恶的爱某艺不好好更新剧集,居然搞起了超前点映… WTF???有什么是我这个贫穷而又尊贵的VIP用户不能看的吗???
在这里插入图片描述
于是我决定开始看小说了!找个网站把小说爬下来慢慢看吧~
先物色一个投缘的小说网站吧
就它了!→ http://www.moyanxsw.com/binbianbushihaitanghong/
在这里插入图片描述

第一步:分析网页

首先需要了解要爬取网站的页面,查看网页源代码。然后根据网页源代码的结构,想好代码的步骤和思路。

在网页开发者模式中查看页面的源代码(F12)

  1. 先来看一下页面的请求方式:
    在开发者模式的Network里找到.html的请求,可以看到请求方式是GET请求,也没有带什么特殊的请求参数之类的~ 比较简单。
    (如果没有看到.html的请求,刷新一下页面就出来了)
    在这里插入图片描述
  2. 然后再看代码结构:
    (不太熟悉html的小伙伴可以使用圈圈里的小箭头,点一下自己想要看的元素,然后右侧就会自动跳转到该元素对应的代码区域的~四不四很简单)

小说网站的话会有两个比较重要的页面:
首先是目录页面,这里会有每一章的标题和链接,点击就会跳转到对应章节。

在目录页面中,可以看到 所有的目录都放在 < div class="book_list">中的<a>标签里,其中每一章的标题里带着一半链接,比如“第一节”是“href="7489410.html"”,那后面实现跳转的时候就需要拼接一下了。
在这里插入图片描述
然后是正文页面,还是以第一章来举栗子:
先看它的地址:http://www.moyanxsw.com/binbianbushihaitanghong/ 加上前面章节里放的链接 7489410.html 就可以了,比较简单。
再看正文部分,是放在< div class="contentbox">中的,也不复杂~
在这里插入图片描述
3. 确定实现思路:
①首先可以通过目录页面获得小说所有章节的链接地址。
②然后通过第一步获得的链接地址,爬取每一章节的正文内容。
③最后把爬取到的正文保存在本地的txt文档中。

第二步:开始编程

1. 定义库
import requests
from bs4 import BeautifulSoup

requests 库是用来发网络请求的,BeautifulSoup 是用来解析和提取 HTML 数据的。
关于它俩的详细说明可以参考我之前的文章呀:爬虫学习笔记——爬取单个网页里的所有图片(入门)

2. 对各步骤分别定义函数
2.1 获取网站数据并解析网页 getHtml():

获取网页数据还是用 requests.get()方法。
res = requests.get(url,params=params,headers=headers) 这样获取到的结果是一个 HTTP 状态码。
还需要用.text 方法再来获取一下这个结果里的文本信息。

#获取网页数据
html = requests.get(url)
htmlCode = html.text

有的网站对于反爬虫力度比较大,请求的时候可以构造一个请求头加上,请求头(Request Headers)在最前面开发者模式中的 Network 里就可以找到。

今天爬取的这个页面很简单,就直接 GET 请求 url 即可,可以啥都不带。
(我承认这段话是从我上篇文章里直接复制来的……)

接下来开始解析网页。
BeautifulSoup4 是将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,之后就可以利用 soup 加标签名轻松地获取这些标签的内容了。

参考beautifulsoup菜鸟教程

BeautifulSoup(markup,'html.parser')

  • markup 是被解析的 html 格式的内容
  • html.parser 表示解析用的解析器
#解析网页
soup = BeautifulSoup(htmlCode,'html.parser')
2.2 获取章节目录 getList():

因为之前确定的实现思路是通过目录来获得小说所有章节的链接地址,然后分别对每一章内容进行爬取,所以接下来先要获得章节的目录。

前面分析过 在目录页面中,所有的目录链接都放在 < div class="book_list">中的<a>标签里,那么这里就可以用 soup.find('div', class_="book_list").find_all('a') 来获得所有符合条件的 <a> 标签了。
然后再看 <a> 标签的结构:
在这里插入图片描述
我们最终需要拿到的是 a 标签中的 href 属性值,获得href属性值的方法是a['href']
(这个小说的目录都是“第一节”、“第二节”这样,没什么用,就不用取出来了,如果是带有章节名称的话,可以考虑用 .text方法来获得 a 标签里的文字内容。)

这部分的代码是这样的:

soup = getHtml(url)
#查找所有章节的链接
listBox = soup.find('div', class_="book_list").find_all('a')
#新建列表用来储存list的url
bookLists = []
for i in listBox:listUrl = i['href']#放进列表里bookLists.append(listUrl)
2.3 获取各章节正文 getNovelContent():

根据前面分析页面的结果,正文部分,是放在各个章节对应的正文页面的 < div class="contentbox">中的,直接用 soup.find('div', class_="contentbox")就可以获得对应 div 中的所有内容,以第一章为例,打印出来看一下。
在这里插入图片描述
现在这个内容是包含了 html 代码部分的,所以还需要用 .text来获取其中的内容,再打印看看~ 是不是干净多了~
在这里插入图片描述
但是发现每一章后面还有几句话有点不好看,比如: “本章有错误,我要提交上一章 返回目录 下一章”、“小提示:按 回车[Enter]键 返回书目,按 ←键 返回上一页, 按 →键 进入下一页。” 之类的……
回到网页里看一下:
在这里插入图片描述
原因是正文底部的控件和文字也都包含在了 < div class="contentbox">中了,暂时想不到其它比较好的获取正文内容的方法了,就只能把正文取出来以后再把多余的文字删掉了。

之后再简单处理一下,用.strip() 方法去掉收尾空格以后这部分就完成啦~

soup = getHtml(url)
#获得需要的正文内容
content = soup.find('div', class_="contentbox").text
content = content.strip()
contentCut = content.replace("本章未完,点击[ 下一页 ]继续阅读-->>","").replace("本章有错误,我要提交上一章 返回目录 下一章","").replace("小提示:按 回车[Enter]键 返回书目,按 ←键 返回上一页, 按 →键 进入下一页。","")

需要注意的是这里 getNovelContent() 的入参必须是章节正文页面的链接哟~ 就是目录页面地址和各章节 href 属性值拼接后的地址。

2.4 获得标题 getTitle():

保存下来之前我还想把标题拿到,这样保存的时候就可以直接用小说的标题作为文件名了。
(对于一篇小说似乎看起来没什么用,但是如果要爬取多本小说的话,这个方法还是很有用的~)

还是在目录页来看,这个标题是放在<div class="book_info">中的<h1 >标签里,所以直接用 soup.find('div',class_="book_info").find('h1').string就可以拿出来了。
在这里插入图片描述

soup = getHtml(url)
title = soup.find('div',class_="book_info").find('h1').string
2.5 爬取下来后保存到本地 saveNovel():

保存时需要注意两点:
① 拼接完整的章节链接地址后才能调用获取各章节正文的函数 getNovelContent()

#获取各章节目录,这里的url是目录页的url
bookLists = getList(url) 
for listUrl in bookLists:#拼接完整的章节链接地址chapterUrl = url + listUrlchapterContent = getNovelContent(chapterUrl)

② 读写文件的方法
爬取小说和爬取图片的方法不同,小说需要将爬取到的内容写入本地文件中。
Python 的文件读取有两个最基本的用法,其一 with open(…) as …,其二 open()配合close()。这里我选择用第一种方法啦~

简单扩展一下:
File.open() 方法 用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数。
File.write() 方法 用于向文件中写入指定字符串。
File.close() 方法 用于关闭一个已打开的文件,关闭后的文件不能再进行读写操作。使用 close() 方法关闭文件是一个好的习惯哟~。

(想起了 “把大象装进冰箱,总共分几步?”哈哈哈)

说明一下open()函数:
open(name[, mode[, buffering]])
参数说明:

  • name : 一个包含了你要访问的文件名称的字符串值。
  • mode : mode 决定了打开文件的模式:只读,写入,追加等。这个参数是非强制的,默认文件访问模式为只读®。
  • buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。(这个没看明白)

r: 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
a: 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

因为爬取小说的时候是一章一章地写入文件的,所以打开文件的模式需要用 “a”——追加模式

这部分的代码如下↓,在打开文件的时候加上了解码方式’utf-8’。

#获得章节目录
bookLists = getList(url)
#获得小说标题
title = getTitle(url)
#num用于下载时计数
num = 1
#以追加模式打开文件
with open('%s.txt'%title, 'a' ,encoding='utf-8') as f:for listUrl in bookLists:#拼接完整的章节链接地址chapterUrl = url + listUrl#获得对应章节正文内容chapterContent = getNovelContent(chapterUrl)#写入章节正文f.write(chapterContent)print('***第{}章下载完成***'.format(num))num += 1
#关闭文件
f.close()

第三步:执行

run run run!
文件默认是与该 .py 文件在同一目录下的。
在这里插入图片描述
愉快地去看小说吧~
在这里插入图片描述

附上完整代码:

import requests
from bs4 import BeautifulSoupdef getHtml(url):#获取网页数据html = requests.get(url)htmlCode = html.text#解析网页soup = BeautifulSoup(htmlCode,'html.parser')#返回解析后的页面内容return soupdef getTitle(url):soup = getHtml(url)title = soup.find('div',class_="book_info").find('h1').stringreturn title#获取各章节目录链接
def getList(url):soup = getHtml(url)#查找所有章节的链接listBox = soup.find('div', class_="book_list").find_all('a')#新建列表用来储存list的urlbookLists = []for i in listBox:listUrl = i['href']#放进列表里bookLists.append(listUrl)return bookLists#获取各章节正文
def getNovelContent(url):soup = getHtml(url)#获得需要的正文内容content = soup.find('div', class_="contentbox").textcontent = content.strip()#这个地方我处理的有点粗糙了,需要根据正式情况来用contentCut = content.replace("本章未完,点击[ 下一页 ]继续阅读-->>","").replace("本章有错误,我要提交上一章 返回目录 下一章","").replace("小提示:按 回车[Enter]键 返回书目,按 ←键 返回上一页, 按 →键 进入下一页。","")return contentCut#保存到本地
def saveNovel(url):bookLists = getList(url)title = getTitle(url)num = 1with open('%s.txt'%title, 'a' ,encoding='utf-8') as f:for listUrl in bookLists:#拼接完整的章节链接地址chapterUrl = url + listUrlchapterContent = getNovelContent(chapterUrl)f.write(chapterContent)print('***第{}章下载完成***'.format(num))num += 1f.close()if __name__ == '__main__':url='http://www.moyanxsw.com/binbianbushihaitanghong/'saveNovel(url)
后记
  1. 这种按照目录 对目录中各个章节页面正文内容 进行爬取的方法有一个缺点,比如今天爬取的这篇文章,其实它目录中的每一章又被分为了几页来展示,按照今天这种方法只能爬取到每章的第一页内容,剩下的内容都没有拿到……
    但是对于那种目录跳转到的页面中有完整的一章内容的小说,还是可以用的。
    所以我决定!找时间换一种方法,再写一篇!

  2. 其实《鬓边不是海棠红》中,齐王爷和宁九郎这对老年CP也超好磕的啊喂!
    一个是贱嗖嗖忠犬王爷,一个是清冷傲娇梨园尚书,满屏幕都能感受到那种温柔的珍惜呀!(文字来自豆瓣小组 丢腻腻同学~
    在这里插入图片描述

撒花~~~✿✿ヽ(°▽°)ノ✿


http://www.ppmy.cn/news/583690.html

相关文章

婚宴座位图html5,20桌婚宴座位安排图(婚宴座位顺序如何安排?)

酒席上如何安排座次 这个可分为正式的大型和分正式的小型宴会: 正式或大型宴会: 正式或大型宴会一般都排席位,也可只排部分客人席位,其他人员只排桌次或自由入座。 1、宴会席位主要是根据出席人员礼宾次序安排的,同时还要综合考虑政治关系、语言使用、宗教信仰和专业等诸因…

哈尔滨计算机管理,哈尔滨戴斯酒店计算机管理系统.doc

哈尔滨酒店计算机管理系统的建议 FRONTIER前台管理系统方案 日常管理 散客预订&#xff0c;团队预订 客房更改房态&#xff0c;检查差异房 自动分配干净房 前台收银&#xff0c;转移帐户项目&#xff0c;团队快速结帐 打印客户所需报表&#xff0c;并支持屏幕预览 在同一屏幕中…

哈尔滨计算机管理,哈尔滨戴斯酒店计算机管理完整系统.doc

哈尔滨戴斯酒店计算机管理完整系统 哈尔滨酒店计算机管理系统的建议 FRONTIER前台管理系统方案 日常管理 散客预订&#xff0c;团队预订 客房更改房态&#xff0c;检查差异房 自动分配干净房 前台收银&#xff0c;转移帐户项目&#xff0c;团队快速结帐 打印客户所需报表&#…

在艳遇的6个小时里,我们都说了啥?

前天艳姐说&#xff0c;明天准备搞个好点的地方&#xff0c;西塔怎么样。西塔70层。 王军说&#xff0c;可以得很。 我也说&#xff0c;好啊。 我还没有去过西塔&#xff0c;不知道是干嘛的&#xff0c;但是听这名字我想应该是很尊贵的&#xff0c;地标性的商业大厦。70层&…

玉米社:什么是口碑营销,怎么样进行口碑营销?

什么是口碑营销&#xff0c;怎么样进行口碑营销&#xff1f; 口碑营销是指通过制定一定的口碑推广计划&#xff0c;从而让消费者自动自发传播产品以及服务的良好评价&#xff0c;从而使更多潜在用户了解产品、改变观念、甚至影响其购买决策的营销行为。 比较知名的口碑营销事件…

【Python教程】十四、找不到对象?用Python自己写一个|类与对象(二)

更多教程请私信~ 来源&#xff1a;思路实验室 作者&#xff1a;室长 大家好&#xff0c;欢迎收看思路实验室出品的Python入门教程&#xff0c;我是室长。 书接上文&#xff0c;我们面对动物园甲方爸爸的要求有了一定的思路&#xff0c;它可以是这样的&#xff1a; 动物园…

CSS - 响应式布局(一)媒体查询

目录 响应式布局 引子 理解响应式网页和响应式布局原理 媒体查询 什么是媒体查询&#xff1f; 什么是媒体类型&#xff1f; 什么是媒体特性&#xff1f; 媒体查询语法 仿三星官网首页 响应式布局 引子 通过前面两节的学习 CSS - 移动端布局&#xff08;一&#xff…

别克GL8,这样的改装太令人兴奋了

别克GL8一直深受广大爱车人士的喜爱&#xff0c;别克GL8的改装也是层出不穷&#xff0c;下面我们一起来看看这款的改装吧&#xff01; 前脸换上了“雅典娜”的前脸&#xff0c;视觉效果非常棒&#xff0c;不仅在格栅的设计上极其夸张&#xff0c;它的内饰更是可完全比肩商务舱&…