Python爬取《遮天》小说
上学期某门课程大作业需要用到爬取网站相关的技术对某网站进行爬取,自己也试着在网上学习了一些爬取网站相关的浅显内容,最后实现了爬取。今天,就再以一个小型的项目来练手,目标是爬取《遮天》这部小说。
ps : 本实例仅作为练习使用,推荐支持正版小说
爬虫
什么是爬虫?
爬虫是一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。通俗的讲,就是一只爬虫或者蜘蛛,在互联网这张大网中,可以按照我们的心意,爬到对应的地方,并将网页中的信息反馈给我们。
爬虫协议?
robots协议也称爬虫协议、爬虫规则等,是指网站可建立一个robots.txt文件来告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取,而搜索引擎则通过读取robots.txt文件来识别这个页面是否允许被抓取。但是,这个robots协议不是防火墙,也没有强制执行力,搜索引擎完全可以忽视robots.txt文件去抓取网页的快照。(来源于百度百科词条——robots协议)
我们可以通过在网站url的结尾添加/robots.txt查看
如何爬虫?
现如今常见的爬虫工具有很多,如requests、XPath、lxml、BeautifulSoup4、Seleninum等。一个简单的爬虫,通常只需要获取网页url,解析网页内容,得到需要爬取的内容,本次爬虫所使用的是urllib库中的request以及BeautifulSoup4。
开发环境
你可以使用PyCharm,好处是简单易上手,如今PyCharm甚至可以一键自动为你下载python(不过好像不会自动添加到环境变量中),许多视频教程也以PyCharm作为开发主力。
当然,你也有其他的选择,比如vscode+python,如果有需要的话,这里我或许也会写一个教程。
本次开发较为小型,就使用vscode吧。
进行代码的编写前,请确保你的python解释器中已经下载好了bs4,urllib应该已经在python3中存在了,无需手动下载。你可以通过命令行终端输入pip list看是否bs4包已下载。如未包含,可以通过pip install bs4进行下载。
正片开始
先查看一下爬虫协议
可以看出,网站对于爬虫爬取内容并没有加以限制
获取每一章节的url和标题
开发者模式查看导航页网页源码,发现每一章节的url和标题都在类名为"box_con",id=“list”,标签名自上而下为dl dd,故可通过BeautifulSoup 使用select方法获取每一章节的url。
# 可以看到每一章的url以及标题位置相似
pattern = soup.select('.box_con #list dl dd')
对之前select下来的内容进行分解,这里可以用到正则表达式来帮助我们处理。可以发现url的处于a href=" 和"之间,而标题处于html">和</a之间,所以可以用如下正则表达式提取。
import re
findLink = re.compile(r'<a href="(.*?)"')
findTitle = re.compile(r'.html">(.*?)</a>')
为了不轻易被识别为爬虫,我们可以传入一个head参数,伪装成浏览器正常访问。
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36"
}
获取每一章节的文本内容
先前已经获得了每一章节的url,获取网页内容的操作与先前对导航页进行的操作类似,不加以赘述。查看网页源码,如上图,所有小说文本内容均在id="content"中,用BeautifulSoup的find操作(只有一个,不要用findall)
效果图如上,可以看到已经将文本内容提取出来了,但是发现有许多无关数据,故还需对数据进行清洗。这里不一样的地方每一章节都一样,就直接替换吧。
# 清洗文本,去除无关内容
text = str(pattern1).replace("<br/><br/>", "\n")
text = text.replace('<div id="content">', '')
text = text.replace(
'<script>chaptererror();</script><br/>请记住本书首发域名:booktxt.net。顶点小说手机版阅读网址:m.booktxt.net</div>', '')
看看清洗后的文本,就没有那些奇奇怪怪的东西啦。
存储文本
看小说肯定得一章一章的看啊,所以不如就用.txt文件存储吧,先前存储的标题也就可以发挥作用了。设置好路径,文件以w方式写入。
# 以.txt文件形式存储
file = open(r'F:\遮天\{}.txt'.format(
title[i]), mode='w', encoding='utf-8')
file.write(text)
file.close
来看看效果
如此我们本次爬取小说的任务就完成啦。我本次作为演示只爬取了前面20章左右内容,你当然可以将整本小说都爬取下来。
完整代码
import re
from bs4 import BeautifulSoup
import urllib.request
findLink = re.compile(r'<a href="(.*?)"')
findTitle = re.compile(r'.html">(.*?)</a>')
def main():
# 标题页的url
url = "https://www.booktxt.net/1_1213/"
# 头部伪装
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36"
}
# 获取网页信息
request = urllib.request.Request(url, headers=head)
response = urllib.request.urlopen(request)
html = response.read().decode('gbk')
soup = BeautifulSoup(html, 'html.parser')
# 可以看到每一章的url位置相似
pattern = soup.select('.box_con #list dl dd')
# 存储标题
title = []
for item in range(20):
# 每一章节的url
pattern[item] = 'https://www.booktxt.net' + \
re.findall(findLink, str(pattern[item]))[0]
# 添加每一章的标题
title.append(re.findall(findTitle, str(
soup.select('.box_con #list dl dd')[item]))[0])
for i in range(6, 20):
url1 = pattern[i]
request1 = urllib.request.Request(url1, headers=head)
response1 = urllib.request.urlopen(request1)
html1 = response1.read().decode('gbk')
soup1 = BeautifulSoup(html1, 'html.parser')
# 发现文本内容在id="content"下
pattern1 = soup1.find(id="content")
# 清洗文本,去除无关内容
text = str(pattern1).replace("<br/><br/>", "\n")
text = text.replace('<div id="content">', '')
text = text.replace(
'<script>chaptererror();</script><br/>请记住本书首发域名:booktxt.net。顶点小说手机版阅读网址:m.booktxt.net</div>', '')
# 以.txt文件形式存储
file = open(r'F:\遮天\{}.txt'.format(
title[i]), mode='w', encoding='utf-8')
file.write(text)
file.close
if __name__ == '__main__':
main()