python爬取有声小说网站实现自动下载实例

最近想下载一些有声小说,但是苦于没有找到批量下载,每次都是单集单集的下载的,觉得很麻烦,就考虑用python写一个爬虫来实现自动搜集小说,自动下载。下面就是开始展开漫漫的爬虫之路。

基础的就不多说了,重点就是针对在项目中遇见的一些问题进行记录。主要就以下三个方面进行展开:

1.正则表达式的使用

2.编码格式

3.如何获取js动态加载生成的内容

1.正则表达式的使用

正则表达式主要是用于匹配相应的标签,这个可以快速定位出需要的标签,使爬虫更有效率。

如:

考虑使用如下正则表达式:

self.down_pattern = '<a title=.+? href=(.\/down.+?)target=.*?>.+?</a>'

一开始编写正则的时候,主要是刚开始使用,很多不是很熟悉,使用了\w来匹配,后来发现无法匹配,后来换成了.来匹配,同时使用了非贪婪匹配。非贪婪匹配就是在*+后加上?即可。具体的正则表达式相关的知识请参阅别的教程,总之正则是个很大很大的坑,日后还有再找机会慢慢填。

2.编码格式

编码格式也是个很恼火的问题,在编写爬虫爬取网页经常爆出unicodeencodeerror错误,几乎都是中文导致的影响,所以每次以后记住,如果网页中有中文出现,返回的响应用decode('gbk')或者decode('gb2312')解码,这样中文就可以显示正确了。同时如果在url中出现了中文,那么想当然也要进行相应的编码,可以使用urllib.parse.quote()来进行相应编码,一般默认utf-8,但在运用听书网的搜索功能时,发现它传入的中文转换成了gb2312格式,那么只需quote传入gb2312就行。这里也是当时费了一点时间,所以提醒自己日后一定要注意多种格式编码。后来借助一个在线编码转换网站,成功发现了它是转换成了gb2312,之前都是默认用的utf-8。这里安利一下这个网站,感觉方便的。http://tool.chinaz.com/tools/urlencode.aspx

3.获取js动态生成的内容

在编写自动下载小说的过程中发现,当我访问每个下载链接的主页的时候,我爬取不到下载的url,咦,当时就觉得很奇怪,查看了源之后发现确实没有写在源中,于是猜测可能是动态加载了,好吧,那就乖乖打开开发人员工具吧。之前有过爬取豆瓣排行榜的经历,所以首先想到的是xhr类型,返回一个json格式数据,后来发现并不是,接着查看了网页加载后的所有动态文件,发现一个叫down.js的文件有点意思啊,查看了它的响应结果,果真,就是下载地址。好吧,那么问题就来了,如果使用python3来爬取js动态加载的内容呢。这里就最简单的考虑了使用selenium+edge来模拟浏览器访问,等加载完成之后,再读取相应地址。这里呢安装selenium还是挺简单的,顺带还要下载一个edge的运行驱动吧,把驱动放在一个配置了path的目录下,这样似乎才可以正确调用浏览器。后面还要继续在学下selenium。

下面是全部代码:

	import urllib.request
	import urllib.parse
	import re
	import os.path
	import selenium.webdriver
	
	# <a title="第000章" href="/down/?26-0-0.html" target="_blank">第000章</a>
	
	
	class TingSpider:
	    def __init__(self, bookname):
	        self.down_pattern = '<a title=.+? href=(.\/down.+?) target=.*?>.+?</a>'  # 匹配下载主页
	        self.pattern = '<a title=.+? href=.+? target=.*?>(.+?)</a>'  # 匹配章节名称
	        self.hotpattern = '<a href=(.*?) title=.*>.*</a></h2>(\d*?)<b>'  # 匹配书的热度的正则表达
	        self.index_url = "http://www.520tingshu.com/search.asp?searchword="  # 搜索主页
	        self.down_url_pattern = '<a href=(.+)\/.*\.mp3" target=.*?>.+?</a>'  # 下载链接的地址
	        self.bookname = bookname
	
	    def __getmax(self, result):  # 获取搜索的结果中热度最高的那本书
	        max_item = None
	        for i in range(len(result)):
	            if max_item == None:
	                max_item = result[i]
	            elif int(result[i][1]) > int(max_item[1]):
	                max_item = result[i]
	        return max_item
	
	    def __searchbook(self):  # 获得要搜索的书的首页地址
	        file = urllib.request.urlopen(self.index_url + urllib.parse.quote(self.bookname, encoding='gb2312'))
	        data = file.read().decode('gbk')
	        result = re.findall(self.hotpattern, data)
	        if result is None:
	            raise 'No book found'
	        res = self.__getmax(result)
	        new_url = "http://www.520tingshu.com"+res[0].replace('"', '')
	        return new_url
	
	
	    def __getlist(self):  # 获得该有声小说所有的章节名,小说下载页的url
	        bookurl = self.__searchbook()
	        req = urllib.request.Request(bookurl)
	        file = urllib.request.urlopen(req)
	        data = file.read().decode('gbk')
	        result = re.findall(self.pattern, data)
	        tmp_url = re.search(self.down_pattern, data)
	        return result, "http://www.520tingshu.com" + tmp_url.group(1).replace("'", '')
	
	    def __getdownurl(self, downpage):  # 获取下载链接地址的除去文件名的地址
	        brower = selenium.webdriver.Edge()
	        brower.get(downpage)
	        brower.maximize_window()
	        result = re.search(self.down_url_pattern, brower.page_source)
	        brower.close()
	        return result.group(1).replace('"', '') + '/'
	
	    def __getAllUrl(self):  # 获得所有的章节的下载地址
	        url = []
	        result, downpage = self.__getlist()
	        down_url = self.__getdownurl(downpage)
	        for item in result:
	            tmp_url = down_url + item + ".mp3"
	            url.append(urllib.request.quote(tmp_url, safe='/:?='))
	        return url
	
	    def down_file(self):
	        result = self.__getAllUrl() # 所有的章节对应的下载地址
	        for i in range(len(result)):
	            s = str(i)+".mp3"
	            if self.__exist(s) == False:
	                self.__downfile(result[i], s)
	
	    def __downfile(self, url, filename):  # 将文件下载到本地
	        file = urllib.request.urlopen(url)
	        data = file.read()
	        with open(filename, "wb") as f:
	            f.write(data)
	
	    def __exist(self, s):
	        if os.path.exists(s):
	            return True
	        else:
	            return False
	
	
	test = TingSpider("诛仙")
test.down_file()
代码地址:https://github.com/xiaoHzp/python/blob/master/Ting_shu.py
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值