Fork me on GitHub

明朝那些事儿

爬虫案例-明朝那些事儿

三月份到四月初花了很长的时间看了一本小说—《明朝那些事儿》,几乎一整个月的时间都在看,越看越入迷,这就是小说的魅力吧。

故事从朱元璋的乞讨要饭开始,经过不断地残酷战争,击败各种对手,建立了明朝;再到后来燕王朱棣起兵造反,接着戚继光抗击倭寇;后来又有明朝出现了最有名的内阁首辅大臣—张居正,大刀阔斧地进行改革,明朝进入鼎盛时期;最后清朝入关,明朝还是败在了崇祯的手上,准确的说是:注定会败在他的手上。正如文中写到的那样:

嗟尔明朝,气数已尽

书讲述的不仅仅是历史,权利、希望、痛苦、气节、孤独、残暴、邪恶、忍耐、坚持、真理、忠诚……在书中样样都有。在书的最后,作者写了一首诗,摘录在这里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
当蜘蛛网无情地查封了我的炉台
当灰烬的余烟叹息着贫困的悲哀
我依然固执地铺平失望的灰烬
用美丽的雪花写下:相信未来

当我的紫葡萄化为深秋的露水
当我的鲜花依偎在别人的情怀
我依然固执地用凝霜的枯藤
在凄凉的大地上写下:相信未来

我要用手指那涌向天边的排浪
我要用手掌那托住太阳的大海
摇曳着曙光那枝温暖漂亮的笔杆
用孩子的笔体写下:相信未来

我之所以坚定地相信未来
是我相信未来人们的眼睛
她有拨开历史风尘的睫毛
她有看透岁月篇章的瞳孔
不管人们对于我们腐烂的皮肉
那些迷途的惆怅、失败的苦痛
是寄予感动的热泪、深切的同情
还是给以轻蔑的微笑、辛辣的嘲讽
我坚信人们对于我们的脊骨
那无数次的探索、迷途、失败和成功
一定会给予热情、客观、公正的评定

是的,我焦急地等待着他们的评定
朋友,坚定地相信未来吧
相信不屈不挠的努力
相信战胜死亡的年轻
相信未来、热爱生命

# by:当年明月

爬取小说

数据来源

本文介绍的如何使用Python爬取一个网站上关于这本书的部分章节。

网站首页:https://www.kanunu8.com/

爬取主链接:https://www.kanunu8.com/files/chinese/201102/1777.html

爬取内容

1、章节标题

2、章节正文内容

以第一章为例:我们点击“第一章 童年”可以进入第一章的正文部分。

爬取结果

看看最终爬取到的数据。在本地目录下生成的一个文件夹:《明朝那些事儿》下面就有我们爬取到的33个章节的内容,包含前言和引子部分。

爬取相关库

在本次爬虫中使用到的相关库

1
2
3
4
from multiprocessing.dummy import Pool   # 伪多进程,加快爬取速度
import requests # 发送请求,获取网页数据
import re # 正则模块,解析数据
import os # os模块处理文件和目录

爬取流程图

网页分析

分析一下网页的规律

1
2
3
4
5
6
# 主页面:https://www.kanunu8.com/files/chinese/201102/1777.html

# 前言:https://www.kanunu8.com/files/chinese/201102/1777/40607.html
# 引子:https://www.kanunu8.com/files/chinese/201102/1777/40608.html
# 第一章:https://www.kanunu8.com/files/chinese/201102/1777/40609.html
# 第三十一章:https://www.kanunu8.com/files/chinese/201102/1777/40639.html

发现了规律:每个章节的页面都有自己的URL后缀加以区分。看下网页源码找出URL地址:

上面已经发现了每个章节的URL地址的后缀

源代码

正则写的不太好,地址还需要切片一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import requests
import re
import os
from multiprocessing.dummy import Pool

start_url = 'https://www.kanunu8.com/files/chinese/201102/1777.html'

def get_source(url):
"""
函数作用:获取网页内容,包含初始网页和每个章节的网页
参数:
URL地址,包含首页或者正文页地址
返回值:
网页源码内容
"""
response = requests.get(url=url)
result = response.content.decode('gbk')
return result # 返回初始网页源码

def get_toc(source_code):
"""
函数说明:从初始网页中解析出来每个章节的URL地址,以待后续爬取每个章节的正文内容
参数:
初始页面的源码
返回值:
正文页的URL地址构成的列表:[url1,url2,......,url33]
"""
toc_url_list = []
toc_url = re.findall('.*?<td.*?><a href="(.*?)">.*?</a></td>',source_code,re.S)
for url in toc_url:
toc_url_list.append(start_url.split('1777')[0] + url) # !!! 注意每个章节地址的构建
return toc_url_list[1:34] # 正则写的不好,还要切片一次


def get_article(article_code):
"""
函数说明:传入每个章节的源码,获取章节名、正文内容
参数:
正文页的源码内容
返回值:
章节名称
正文内容
"""
chapter_name = re.search('color="#dc143c">(.*?)</font>',article_code,re.S).group(1) # 获取匹配到的第一个内容
article_text = re.search('<p>(.*?)</p>',article_code, re.S).group(1) # p 标签之间的全部内容
article_text = article_text.replace('<br />','') # 替换文章中的空格符号
return chapter_name, article_text


def save(chapter,article):
"""
函数说明:根据每章名字和正文内容进行保存
参数:
章节名称
该章节正文内容
返回值:无
"""
os.makedirs("明朝那些事儿",exist_ok=True)
with open(os.path.join('明朝那些事儿', chapter + '.txt'), 'w', encoding='utf-8') as f:
f.write(article)


def query_article(url):
"""
函数说明:传入正文URL地址,获取到章节名和正文,并保存
参数:
正文页的URL地址
返回值:无
"""
article_code = get_source(url) # 获取网页源码的函数
chapter, article_text = get_article(article_code) # 通过网页源码获取到章节名和正文内容
save(chapter, article_text) # 保存正文


if __name__ == "__main__":
"""
函数说明:
1、传入初始URL得到初始页的网页源码
2、通过初始页的源码得到所有章节的url地址列表
3、调用query_article,对每个步骤2中的每个URL地址执行函数功能,最终保存
"""
source_code = get_source(start_url) # 初始化网页获取源码
toc_url_list = get_toc(source_code) # 传入源码获取全部的URL地址
pool = Pool(4)
pool.map(query_article, toc_url_list) # 对每个地址执行query_article函数,获取对应的章节名和正文内容,最后保存

正则切片问题

首页源码返回内容解析的结果:

1
2
3
4
5
6
7
8
9
10
11
url = 'https://www.kanunu8.com/files/chinese/201102/1777.html'
response = requests.get(url=url)
res = response.content.decode('gbk')

toc_url_list = []
toc_url = re.findall('.*?<td.*?><a href="(.*?)">.*?</a></td>',res,re.S)
print(toc_url)
for url in toc_url:
toc_url_list.append(start_url.split('1777')[0] + url) # !!! 注意每个章节地址的构建

toc_url_list

切片之后的有效URL地址:

本文标题:明朝那些事儿

发布时间:2021年04月18日 - 18:04

原始链接:http://www.renpeter.cn/2021/04/18/%E6%98%8E%E6%9C%9D%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Coffee or Tea