此程序仅为学习python所写。
Python3中集成了Urllib库,而Urllib与Urllib2在Python2的复杂程度确实差强人意。在Python3上,我们选择requests库直接get网页,再通过Beautifulsoup4对所得到的数据进行清洗。其难点主要存在于数据清洗时Html语言的分析,以及得到数据进行转字符编码得到中文。
我们所爬取的网页是笔趣阁的一篇小说
小说目录页面URL为:http://www.biqukan.com/1_1094/
我们分为三部分进行程序讲解与分析。
网页在浏览器上显示时,是以代码的方式传递给浏览器,再通过浏览器译码显示为当前显示的网页。
所以我们需要借助Requests模拟人对网页的读取请求,得到网页的Html数据后,再进行数据清洗。
HTML中定义了八种网页请求,在这里仅介绍最简单的两种:GET 与 POST
以上是在网站开发中常用的两种方法。并且一般情况下都会遵循使用的原则。但是有的网站和服务器为了做反爬虫机制,也经常会不按常理出牌,有可能一个应该使用get方法的请求就一定要改成post请求,这个要视情况而定。
当然他就有网页死活不让你爬你一点办法都没有所以直接保存HTML文件也不是不行
对于目标网页,由于无动态生成等干扰格式,我们可以直接采用GET命令捕获Html数据进行分析。
def get_download_url(self):
req = requests.get(url = self.target)
html = req.text
div_bf = BeautifulSoup(html)
div = div_bf.find_all('div', class_ = 'listmain')
a_bf = BeautifulSoup(str(div[0]))
a = a_bf.find_all('a')
#统计章节数
self.nums = len(a[15:])
for each in a[15:]:
self.names.append(each.string)
self.urls.append(self.server + each.get('href'))
由于我们需要读取出全部章节的下载链接,所以我们需要从Html中读取到所以的Url链接。一般来说,从目录章节读取到的一般均为该网站的子节点或者孙节点。而且此网站也是如此。
由于插入图片的操作繁琐我决定不插入图片
程序在读取到子节点后会将子节点与父域名进行结合得到一个完整的章节链接。Openurl就可以直接获取到该网页的Html内容。
def get_contents(self, target):
req = requests.get(url = target)
html = req.text
bf = BeautifulSoup(html)
texts = bf.find_all('div', class_ = 'showtxt')
texts = texts[0].text.replace('\xa0'*8,'\n\n')
texts = texts.encode('ISO-8859-1').decode('GBK')
return texts
在分析Html后,此网站所需要的文本均在div标签栏中存放,借助BF4,我们可以很轻易的清洗出所需要的内容。
需要注意的是,在清洗出div中的内容后,我们所得到的是乱码格式。主要是因为网页所保存的个数为GBK,而我们按照UTF-8格式保存下来后会造成乱码。这里我们选择,先encode编码为ISO-8891-1格式,其余格式均无法完整的被译码,再解码decode为GBK格式,这样我们可以完整的得到这个网页的目标内容。
def writer(self, name, path, text):
with open(path, 'a', encoding='utf-8') as f:
f.write(name + '\n')
f.writelines(text)
f.write('\n\n')
在得到目标文字后,我们只需要新建一个txt文档,将得到的文本写入txt中即可得到所需要的小说。
if __name__ == "__main__":
dl = downloader()
dl.get_download_url()
print('《一念永恒》开始下载:')
for i in range(dl.nums):
dl.writer(dl.names[i], '一念永恒.txt', dl.get_contents(dl.urls[i]))
sys.stdout.write(" 已下载:%.3f%%" % float(i/dl.nums) + '\r')
sys.stdout.flush()
print('《一念永恒》下载完成')
构建一个下载程序,借助sys进行下载量的分析,构建循环,再根据循环的数量分析计算下载百分比。
一个简单的爬虫程序就此完成。
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests, sys
class downloader(object):
def __init__(self):
self.server = 'http://www.biqukan.com/'
self.target = 'http://www.biqukan.com/1_1094/'
self.names = [] #存放章节名
self.urls = [] #存放章节链接
self.nums = 0 #章节数
"""
函数说明:获取下载链接
Parameters:
无
Returns:
无
"""
def get_download_url(self):
req = requests.get(url = self.target)
html = req.text
div_bf = BeautifulSoup(html)
div = div_bf.find_all('div', class_ = 'listmain')
a_bf = BeautifulSoup(str(div[0]))
a = a_bf.find_all('a')
#统计章节数
self.nums = len(a[15:])
for each in a[15:]:
self.names.append(each.string)
self.urls.append(self.server + each.get('href'))
"""
函数说明:获取章节内容
Parameters:
target - 下载连接(string)
Returns:
texts - 章节内容(string)
"""
def get_contents(self, target):
req = requests.get(url = target)
html = req.text
bf = BeautifulSoup(html)
texts = bf.find_all('div', class_ = 'showtxt')
texts = texts[0].text.replace('\xa0'*8,'\n\n')
texts = texts.encode('ISO-8859-1').decode('GBK')
return texts
"""
函数说明:将爬取的文章内容写入文件
Parameters:
name - 章节名称(string)
path - 当前路径下,小说保存名称(string)
text - 章节内容(string)
Returns:
无
"""
def writer(self, name, path, text):
with open(path, 'a', encoding='utf-8') as f:
f.write(name + '\n')
f.writelines(text)
f.write('\n\n')
if __name__ == "__main__":
dl = downloader()
dl.get_download_url()
print('《一念永恒》开始下载:')
for i in range(dl.nums):
dl.writer(dl.names[i], '一念永恒.txt', dl.get_contents(dl.urls[i]))
sys.stdout.write(" 已下载:%.3f%%" % float(i/dl.nums) + '\r')
sys.stdout.flush()
print('《一念永恒》下载完成')