程序主要功能是爬取读书笔记网站(http://www.mossiella.com/)上的小说下载保存为txt,这里拿《明朝那些事》为例,网址为http://www.mossiella.com/xiandaiwenxue/mingchaonaxieshier/
如果想要爬取别的小说,只需要更改如下的变量即可:
初始化函数
def __init__(self):
self.target = 'http://www.mossiella.com/xiandaiwenxue/mingchaonaxieshier/' #保存要爬取的网址
self.savefile = '明朝那些事.txt' #下载文件的名称
self.dirclass = 'booklist' #目录div的class属性
self.textclass = 'zwcent' #正文div的class属性
self.dirnames = [] #保存目录的列表
self.dirurl = [] #保存每个目录的URL
self.dirnums = 0 #记录一共有多少章节
如下函数是获取小说的每个章节和每个章节的URL
def get_dirurl(self):
code = requests.get(url = self.target).status_code
if code is not 200:
print('请求失败,请检查网络或者URL!')
return
req = requests.get(url = self.target)
req.encoding = 'UTF-8'
bf = BeautifulSoup(req.text, "lxml")
text = bf.find_all('div', class_ = self.dirclass)
for each in text:
dir_bf = BeautifulSoup(str(each), "lxml")
title = dir_bf.find_all('a')
for each in title:
self.dirnames.append(each.string)
self.dirurl.append(each.get('href'))
self.dirnums += 1
req = requests.get(url = self.target)
requests是python实现的简单易用的HTTP库,主要函数如下:
req.encoding = 'UTF-8'
因为我的python版本是是2.7版本,默认编码是ASCII码,要转换为UTF-8。具体编码问题可以看
彻底搞懂Python的字符编码
可以通过如下命令查看python版本号和默认编码
[root@localhost csdn-spider-master]# python
Python 2.7.5 (default, Nov 20 2015, 02:00:19)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform
>>> print platform.python_version()
2.7.5
>>> import sys
>>> print sys.version
2.7.5 (default, Nov 20 2015, 02:00:19)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]
>>> print sys.version_info
sys.version_info(major=2, minor=7, micro=5, releaselevel='final', serial=0)
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
bf = BeautifulSoup(req.text, "lxml")
text = bf.find_all('div', class_ = self.dirclass)
BeautifulSoup
是一个可以从HTML或XML文件中提取数据的Python库,具体使用方法可以查看官方文档。
for each in text:
dir_bf = BeautifulSoup(str(each), "lxml")
title = dir_bf.find_all('a')
for each in title:
self.dirnames.append(each.string)
self.dirurl.append(each.get('href'))
self.dirnums += 1
这段代码是循环获取并保存每个章节的名称和每个章节的URL
我们抓取的html源代码的部分内容如下
如下函数抓取每个章节的正文
def get_context(self):
print(dl.savefile + '开始下载!')
fd = open(self.savefile, 'a')
for i in range(self.dirnums):
req = requests.get(url = self.dirurl[i])
req.encoding = 'UTF-8'
bf = BeautifulSoup(req.text, "lxml")
text = bf.find_all('div', class_ = self.textclass)
ss = re.sub(r'\s+','',str(text[0]))
st = re.findall('><p>(.*?)</p><divclass',ss,re.S)
if len(st) > 0:
sw = re.sub(r'<p>','',str(st[0]))
sy = re.sub(r'</p>', '\n ',sw)
else:
print('no data')
continue
fd.write(self.dirnames[i] + '\n')
fd.write(sy + '\n\n')
sys.stdout.write(" 已下载:%.2f%%" % float((float(i)/float(self.dirnums))*100) + '\r')
sys.stdout.flush()
fd.close()
print(dl.savefile + '下载完成!')
抓取的正文html文件如下
我们需要去掉很多不需要的内容用re 模块中的sub函数即可实现。
ss = re.sub(r'\s+','',str(text[0]))
st = re.findall('><p>(.*?)</p><divclass',ss,re.S)
Re库是Python的标准库,主要用于字符串匹配。sub函数在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串。
re库中采用raw string类型表示正则表达式,表示为:r'text'。raw string是不包含对转义字符再次转义的字符串。\s表示匹配任何空白字符:[<空格>\t\r\n\f\v],+ 表示匹配一次或者多次,.表示匹配任意除换行符"\n"外的字符,*表示匹配前一个字符0或多次,?表示匹配一个字符0次或1次。re.S表示使.匹配包括换行在内的所有字符。上面两句话的作用是将所有的空格换行的空白字符替换为空,然后找出><p>和</p><divclass之间的所有字符。之后将处理之后的文字去掉<p>和</p>写进文件。
程序入口main函数
if __name__ == "__main__":
dl = download()
dl.get_dirurl()
dl.get_context()
执行效果: