最近在学习爬虫,掌握了点匹毛,记录一下自己的学习进程.可运行代码在最后面
一.爬虫思路
尝试去一些盗版小说网站,类似笔趣阁等网站爬取小说,整理格式,清除网页自带的一些广告语,提高阅读质量。
1.通过目录页面来获取所有章节的链接地址以及章节名称,分别存入两个数组当中
2.利用循环来依次访问链接地址,将章节名称以及小说内容写入打开的文本当中
二.过程的实现细节
1.注意网站的编码方式,以及待写入txt文件的编码方式的一致性
2.网站nginx的访问受限处理,很多网站都放在nginx上,设置了访问限制,短时间内大量访问会导致访问受阻,导致打开正则表达式匹配结果为None,后续写入失败。借助try: except :else来处理对应的AttibutionError,并让代码停止等待一段时间再次运行。
3.对于正则表达式的匹配选择,可以在match与search两个函数中任选其一,但正则表达式的应该保持简洁优先的原则。
实现代码:
import re,sys,time #导入使用的一些库
import requests
#https://www.runoob.com/python3/python3-reg-expressions.html :python正则表达式相关内容链接,不清楚的可以去了解一下
def get_node_list(): #通过get_node_list函数获取小说的章节名称及链接
url = 'http://www.biquge.info/74_74132/' #目录地址
url_temp = 'http://www.biquge.info/74_74132/' #目录页面的章节地址大多只有后续部分,手动记录前面部分,用于拼接成完整地址
resp = requests.get(url)
resp.encoding = 'utf-8'
temp = re.search('<div id="list">([\s\S]*?)</dl>',resp.text,re.M|re.I) #re.M与re.I都是匹配修饰符,temp通过group来实现访问group(0)为全部,group(1)为捕获对象1,后续依次类推
m1 = re.compile('<dd><a href="(.*)" title=".*?>(.*)</a></dd>') #用于生成一个正则表达式匹配对象
temp = m1.findall(temp.group(1)) #通过正则表达式匹配所有的子串并返回一个列表,此处是一个二维列表,内部分别是地址后端与章节名
note_list = [] #记录地址
list_name = [] #记录章节名
for i in temp:
if i[1].find(u"第") != -1: #若章节名内有"第"才写入两个列表,可以筛选一些无关章节
note_list.append(url_temp+i[0]) #将获取的地址后端与前面手动设置的地址前段进行拼接
list_name.append(i[1])
return note_list,list_name
if __name__ == '__main__':
link_list,name_list = get_node_list() #获取两个列表
book = open('我师兄实在太稳健.text','w+',encoding='utf-8')
print("小说开始下载")
i = 0
leng = len(link_list)
while i <leng:
res = requests.get(url=link_list[i]) #requests.get(url) 可以获取网页内容,通过response.text方法可以获取内容文本
res.encoding="utf-8"
novel_one = re.match(r'[\s\S]*<div id="content"><!--go-->([\s\S]*)<!--over-->',res.text,re.M|re.I) #匹配章节名以及正文内容
try:
temp = re.sub(r' ',' ',novel_one.group(1)) #此处可以按照自己的阅读习惯进行设置
temp = re.sub('<br/>','\n',temp)
except AttributeError:
time.sleep(10) #若nginx服务器抛出503访问错误,则会导致匹配结果为none,这种情况下,等待一段时间后再继续爬取
else:
book.write(name_list[i]+'\n')
book.write(temp+'\n')
time.sleep(1)
i += 1
sys.stdout.write(" 已下载:%.3f%%" % float(i/leng*100) + '\r') #实时显示爬取进度
sys.stdout.flush()
book.close()
若代码存在问题,可以留言讨论,谢谢