1 LSGO软件技术团队
贡献人:马子轩
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。
If you like the content here, the greatest helpyou can give meis forwarding, so tell your friends and encourage them to learn together.
我们在学习Python之余总想着让其更具趣味性,可以更好地学习。下面我将讲解如何从网站中爬取我们想看的小说。让我们枯燥无聊的学习生涯稍微多些趣味。
需要只是一点点对requests库、Beautiful库及 python 基础知识的了解。
Python版本:Python3.X
运行平台:Windows
IDE:PyCharm
浏览器:Chrome
本次讲解所有代码已放入GitHub上托管。
https://github.com/siwuya520/python-web-crawler.git
了解爬虫
我们一直口口声声说着用爬虫去爬取某某数据。
那么问题来了,什么是爬虫呢?
网络爬虫,别称网络蜘蛛,它是一段程序(一个脚本),能够模拟浏览器自动的浏览网页,来自动地批量地采集我们需要的资源。
废话不多说,开始今天的爬虫之旅。
爬取章节内容
俗话说得好,饭要一口一口吃,路要一步一步走。我们要爬取每一章内容,须先知晓如何爬取一章内容。
本次爬取网站:笔趣阁 http://www.biquge.cm/
本次爬取小说:《修真四万年》 http://www.biquge.cm/6/6217/
第一步,根据URL获取网页的HTML信息
在python3中可以用requests库进行网页爬取。
import requests
if __name__=='__main__':
target='http://www.biquge.cm/6/6217/3638117.html'
req=requests.get(url=target)
print(req.text)
运行结果如下:
我们轻松地获得了HTML信息,但为什么会出现乱码呢?
事实上这是由于字符编码问题引起的。往往用requests库抓取中文网页时容易出现乱码问题。那如何解决呢?
下面介绍两种方法:
(1)我们可以在调用response.text()之前使用response.encoding='编码格式'
这个方法需要我们进入所爬去网站去查看编码格式。
点击鼠标右键,点击检查,得到如下界面:
点击右侧head标签得到如图:
可以很显然看到编码格式为‘gbk’。
所以我们可以写出代码来解决乱码问题:
import requests
if __name__=='__main__':
target='http://www.biquge.cm/6/6217/3638117.html'
req=requests.get(url=target)
req.encoding='gbk'
print(req.text)
运行得到:
(2)使用req.content返回bytes型数据,然后将bytes型数据转化为str数据。
代码如下:
import requests
if __name__=='__main__':
target='http://www.biquge.cm/6/6217/3638117.html'
req=requests.get(url=target)
html=req.content
html_doc=str(html,'gbk')
print(html_doc)
解决完乱码问题后我们得到了我们需要的能理解看懂的html信息,但是,有很多信息是我们不想看到的,我们只想要小说正文内容。我们不关心div、br这些html标签。
那如何把正文内容从这些众多的html标签中提取出来呢?
这就用到了BeautifulSoup库。
同理按上面方法我们查看第一章目标网页:
我们可以看到文章的所有内容都放在了一个名为div的东西下面,这个东西就是html标签。HTML标签是HTML语言中最基本的单位,HTML标签是HTML最重要的组成部分。
我们可以看到,我们所需的文本内容在一个div标签下,这个标签是这样的:
div id="content"
知道了这个内容,我们就可以用BeautifulSoup来提取我们想要的内容了。编写代码如下:
from bs4 import BeautifulSoup
import requests
if __name__=='__main__':
target='http://www.biquge.cm/6/6217/3638117.html'
req=requests.get(url=target)
html=req.content
html_doc=str(html,'gbk')
bf=BeautifulSoup(html_doc)
texts=bf.find_all('div',id="content")
print(texts)
在解析html之前,先创建一个BeautifulSoup对象,BeautifulSoup函数里面的参数就是我们获得的html信息。然后使用find_all方法,获取html信息中所有id属性为content的div标签。
运行代码查看我们匹配结果:
我们可以看到,我们已经顺利匹配到我们关心的正文内容,但是还有一些我们不想要的东西。比如div标签名,br标签,以及各种空格。怎么去除这些东西呢?我们继续编写代码:
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://www.biquge.cm/6/6217/3638117.html'
req = requests.get(url = target)
html = req.content
html_doc=str(html,'gbk')
bf = BeautifulSoup(html_doc)
texts = bf.find_all('div', id="content")
print(texts[0].text)
find_all匹配的返回的结果是一个列表。提取匹配结果后,使用text属性,提取文本内容,滤除br标签。得到:
我们已经顺利获得了一个章节的内容,要想下载正本小说,我们就要获取每个章节的链接。我们先分析下小说目录:http://www.biquge.cm/6/6217/
在网址进行审查得到:
我们看到每个章节的名字存放在了标签里面。标签还有一个href属性。标签定义了一个超链接,用于从一张页面链接到另一张页面。 标签最重要的属性是href属性,它指示链接的目标。
我们将之前获得的第一章节的 URL 和标签对比看一下:
http://www.biquge.cm/6/6217/3638117.html
我们可以看到 标签中href属性存放的属性值/1_1094/5403177.html是章节 URL http://www.biqukan.com/1_1094/5403177.html的后半部分。那这样,我们就可以根据标签的href属性值获得每个章节的链接和名称了。
编写代码如下:
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://www.biquge.cm/6/6217/'
req = requests.get(url = target)
html = req.content
html_doc=str(html,'gbk')
div_bf = BeautifulSoup(html_doc)
div = div_bf.find_all('div', id='list' )
print(div[0])
运行结果:
接下来再匹配每一个标签,并用a.get('href')方法获取href的属性值,使用a.string方法获取章节名。代码如下:
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
server = 'http://www.biquge.cm/'
target = 'http://www.biquge.cm/6/6217/'
req = requests.get(url = target)
html = req.content
html_doc=str(html,'gbk')
div_bf = BeautifulSoup(html_doc)
div = div_bf.find_all('div', id='list' )
a_bf = BeautifulSoup(str(div[0]))
a = a_bf.find_all('a')
for each in a:
print(each.string, server + each.get('href'))
find_all返回的是一个列表,里边存放了很多的标签,所以使用for循环遍历每个标签并打印出来,运行结果如下:
整合代码:
# -*- coding:UTF-8 -*-
from bs4 import BeautifulSoup
import requests, sys
class downloader(object):
# 类说明下载笔趣阁修真四万年,self只有在类的方法中才会有,
# 独立的函数或方法是不必带有self的。self在定义类的方法时是必须有的,
# 虽然在调用时不必传入相应的参数。
def __init__(self): # 初始化变量
# 爬取图书网站,self.server='http://www.biquge.cm/' 的意思
# 就是把外部传来的参数server的值赋值给类downloader自己的属性
# 变量self.server,下面函数可共用
self.server = 'http://www.biquge.cm/'
self.target = 'http://www.biquge.cm/6/6217/'
# 爬取图书主目录所在网址,用来获取每一章节url
self.names = [] # 存放章节名
self.urls = [] # 存放章节链接
self.nums = 0 # 章节数
def get_download_url(self): # 获取下载链接
req = requests.get(url=self.target) # 获得该网页的html信息
html = req.content # #获得html文件
html_doc=str(html,'gbk')
div_bf = BeautifulSoup(html_doc) # 创建一个BeautifulSoup对象
div = div_bf.find_all('div', id='list')
# 匹配div标签,获取id属性list的内容,用find_all是因为获得的是列表
a_bf = BeautifulSoup(str(div[0])) # 以list中的内容构建Beautiful对象
a = a_bf.find_all('a') # 找到所有a标签,a标签中为每一章网址
self.nums = len(a[:]) # 索引从第一章到最后一章,记数
for each in a[:]:
self.names.append(each.string) # 添加a标签下的字符串即章节名
self.urls.append(self.server + each.get('href'))
# 获取每一章链接,用get()方法获取a标签中href属性
def get_contents(self, target): # 获取章节内容
req = requests.get(url=target)
html = req.content
html_doc=str(html,'gbk')
bf = BeautifulSoup(html_doc)
texts = bf.find_all('div', id="content")
# 获取div标签id属性content的内容
texts = texts[0].text.replace('\xa0'*8,'\n')
# 剔除"'div'标签及'id=content'"和br/,
# 提取texts内容中text文本
return texts
def writer(self, name, path, text): # 将爬取的文章内容写入文件
with open(path, 'a' ,encoding='utf-8')as f:
# ‘a’表示追加到文件,encoding='utf-8'表示以utf-8进行编码
f.write(name + '\n') # write方法写入章节名并换行
f.writelines(text) # writelines方法写入文章内容
f.write('\n') # 换行写完一章
# 当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行
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是映射到打开脚本的窗口
sys.stdout.flush()
# 在Linux系统下,必须加入sys.stdout.flush()才能一秒输一个数字
# 在Windows系统下,加不加sys.stdout.flush()都能一秒输出一个数字
print('《修真四万年》下载完成')
到此为止,利用Python爬取小说的过程就全部介绍完了,希望能够帮助大家!See You!
经过8年多的发展,LSGO软件技术团队在地理信息系统、数据统计分析、计算机视觉领域积累了丰富的研发经验,也建立了人才培养的完备体系。
欢迎对算法设计与实现感兴趣的同学加入,与我们共同成长进步。
本微信公众平台长期系统化提供有关机器学习、软件研发、教育及学习方法、数学建模的知识,并将以上知识转化为实践。拒绝知识碎片化、耐心打磨技能、解决实际问题是我们的宗旨和追求。
欢迎关注,请扫描二维码:
领取专属 10元无门槛券
私享最新 技术干货