用Python3爬取网络小说(request+正则表达式)
写代码的由来:
最近开了一本新的小说,但苦于免费app上获取的小说内容不是缺少章节就是章节内容只有一半。于是乎动了从网上爬取这本小说的念头。但大家如果条件允许还是请支持正版。博主接触python不久,如果代码上有问题请多多包含,可以在评论区进行交流,谢谢大家!!
选择爬取的小说网站是“笔趣阁”:
https://www.biquge.info/
笔趣阁上的大部分小说都是免费看的,但不提供txt单个章节或者整本下载,所以如果我们想要一劳永逸获取整本小说的txt文档的话需要编写爬虫程序来获取。
本文使用anaconda实现
也可以使用python3自带的idle实现:
去python官网下载最新版python,安装,然后用打开idle,创建新的py文件,复制代码即可。python官网网址:https://www.python.org/
要确保安装了request模块,没有安装的参考官网文档:http://cn.python-requests.org/zh_CN/latest/
安装:pip3 install requests
我们先来看一下整体代码,然后进行拆解分析:
该代码的功能是:
1.通过获取用户所输入的该小说的地址(如:都市狂少小说的地址:https://www.biquge.info/55_55097/)
2.获取该小说的简要信息,
3.判断是否需要在D盘创建text文件夹,需要的话输入1,
4.再判断以前是否下载过,如果下载过的话清除重新爬取输入1,随后便会在D:/text文件夹下出现一个以该小说名称命名的txt文档
5.开始下载小说的全部内容,并存入该txt文档中。
关于txt文档存放路径方面大家可以自由修改,如想要存到C盘、E盘的其他文件夹都可以通过修改主函数进行实现。
import urllib.request
import re
import os
def open_url(url):
req = urllib.request.Request(url)
req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3676.400 QQBrowser/10.4.3505.400')
page = urllib.request.urlopen(req)
html = page.read().decode('utf-8')
return html
def readtitleinfo(html):
p1 = r'<div id="info">\n<h1>(.+?)</h1>'
title = re.findall(p1, html)
p2 = r'<div id="info">([\s\S]*)</a></p>'
titleinfo_0 = re.findall(p2, html)
titleinfo = changecontent(titleinfo_0[0])
return title[0],titleinfo
def get_mainpageinfo(html):
p = r'<dd><a href="(.+?)" title="(.+?)">'
chapterlist = re.findall(p, html)
url = []
title = []
for each in chapterlist:
url.append(each[0])#字符串形式的子地址
title.append(each[1])#字符串形式的视频标题
return url,title
def down_eachpage(html):
p = r'<div id="content">\n(.+?)\n</div>'
pagecontent = re.findall(p, html)
return pagecontent[0]
def changecontent(content):
s0 = content.replace(' '," ")#用空格符替换' '
s1 = s0.replace('<br/>',"\n") #用换行符替换'<br/>'
s2 = s1.replace('&mdash',"—") #用横线替换'&mdash'
s_replace = s2.replace(';',"") #删除;
while True: #用换行符替换所有的'<br/>'
index_begin = s_replace.find("<")
index_end = s_replace.find(">",index_begin + 1)
if index_begin == -1:
break
s_replace = s_replace.replace(s_replace[index_begin:index_end+1],"")
return s_replace
if __name__ == '__main__':
# url = 'https://www.biquge.info/55_55097/'#笔趣阁的都市狂少
# url = 'https://www.biquge.info/1_1760/'#笔趣阁的武炼巅峰
url = input('请输入笔趣阁该书地址,如都市狂少为:https://www.biquge.info/55_55097/ \n:')
maintitle,maininfo = readtitleinfo(open_url(url))#获取该书信息,maintitle是书名,maininfo是该书相关信息
print('该书信息:\n',maininfo)
getcode_0 = input('是否要在D盘创建text文件夹,若有则不需要,需要创建输入数字1,不需要直接回车或随意输其他数字:')
if getcode_0 == '1':
maindir = 'D:/text' + '/'
os.mkdir(maindir)#创建该类文件夹
maindir = 'D:/text' + '/' + maintitle + '.txt' #该书txt的存放地址
file = open(maindir, 'w+',encoding='utf-8') #创建txt文件并打开
getcode_1 = input('是否要清空文本,要清空输入数字1,不需要直接回车或随意输其他数字:')
if getcode_1 == '1':
file.truncate() #选择是否要清空重新获取
file.write(maininfo)#写入书籍信息
url_each,title = get_mainpageinfo(open_url(url))
print('本书共有',len(title),'个章节待抓取,请耐心等待...')
i=0
for each in url_each:
url_1 = url + each#每章节页面的地址
eachpage_inint = down_eachpage(open_url(url_1))#获取每一页的文章内容
eachpagecontent = changecontent(eachpage_inint)#网页格式转化为文本格式
file.write('\n\n'+title[i]+'\n')#写入每章节的标题
file.write(eachpagecontent+'\n')#写入每章节的内容
if i%10 == 0:
print('已抓取',str(i),'章的内容!')
i = i+1
print('本书已下载完毕!!')
file.close()
接下来我们进行代码拆解分析:
Part1:
该部分的任务是请求网页地址(url),得到网页的html格式的源代码。
import urllib.request
import re
import os
def open_url(url):
req = urllib.request.Request(url)
req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3676.400 QQBrowser/10.4.3505.400')
page = urllib.request.urlopen(req)
html = page.read().decode('utf-8')
return html
Part2:
readtitleinfo 的功能是:读取该书的简要内容,包括该书的名称(title),作者,最后更新日期,类别等。
get_mainpageinfo 的功能是:抓取该书主页面上所有章节的地址(url)和章节名(title)。
def readtitleinfo(html):
p1 = r'<div id="info">\n<h1>(.+?)</h1>'
title = re.findall(p1, html)
p2 = r'<div id="info">([\s\S]*)</a></p>'
titleinfo_0 = re.findall(p2, html)
titleinfo = changecontent(titleinfo_0[0])
return title[0],titleinfo
def get_mainpageinfo(html):
p = r'<dd><a href="(.+?)" title="(.+?)">'
chapterlist = re.findall(p, html)
url = []
title = []
for each in chapterlist:
url.append(each[0])#字符串形式的子地址
title.append(each[1])#字符串形式的视频标题
return url,title
书的主页面如下所示:
Part3:
down_eachpage 的功能是:针对每一章节的html网页源代码,爬取这一章节的内容。
changecontent 的功能是:将爬取得到的html格式的章节内容转化为普通文本格式内容。
def down_eachpage(html):
p = r'<div id="content">\n(.+?)\n</div>'
pagecontent = re.findall(p, html)
return pagecontent[0]
def changecontent(content):
s0 = content.replace(' '," ")#用空格符替换' '
s1 = s0.replace('<br/>',"\n") #用换行符替换'<br/>'
s2 = s1.replace('&mdash',"—") #用横线替换'&mdash'
s_replace = s2.replace(';',"") #删除;
while True: #用换行符替换所有的'<br/>'
index_begin = s_replace.find("<")
index_end = s_replace.find(">",index_begin + 1)
if index_begin == -1:
break
s_replace = s_replace.replace(s_replace[index_begin:index_end+1],"")
return s_replace
章节主页面如下:
Part Main:
主函数:
if __name__ == '__main__':
# url = 'https://www.biquge.info/55_55097/'#笔趣阁的都市狂少
# url = 'https://www.biquge.info/1_1760/'#笔趣阁的武炼巅峰
url = input('请输入笔趣阁该书地址,如都市狂少为:https://www.biquge.info/55_55097/ \n:')
maintitle,maininfo = readtitleinfo(open_url(url))#获取该书信息,maintitle是书名,maininfo是该书相关信息
print('该书信息:\n',maininfo)
getcode_0 = input('是否要在D盘创建text文件夹,若有则不需要,需要创建输入数字1,不需要直接回车或随意输其他数字:')
if getcode_0 == '1':
maindir = 'D:/text' + '/'
os.mkdir(maindir)#创建该类文件夹
maindir = 'D:/text' + '/' + maintitle + '.txt' #该书txt的存放地址
file = open(maindir, 'w+',encoding='utf-8') #创建txt文件并打开
getcode_1 = input('是否要清空文本,要清空输入数字1,不需要直接回车或随意输其他数字:')
if getcode_1 == '1':
file.truncate() #选择是否要清空重新获取
file.write(maininfo)#写入书籍信息
url_each,title = get_mainpageinfo(open_url(url))
print('本书共有',len(title),'个章节待抓取,请耐心等待...')
i=0
for each in url_each:
url_1 = url + each#每章节页面的地址
eachpage_inint = down_eachpage(open_url(url_1))#获取每一页的文章内容
eachpagecontent = changecontent(eachpage_inint)#网页格式转化为文本格式
file.write('\n\n'+title[i]+'\n')#写入每章节的标题
file.write(eachpagecontent+'\n')#写入每章节的内容
if i%10 == 0:
print('已抓取',str(i),'章的内容!')
i = i+1
print('本书已下载完毕!!')
file.close()