01
前言
大家好,我是asong,这是我的第四篇原创文章,这一文,我将介绍网络爬虫系列的教程,使用GO和python分别实现最简单的爬虫------爬取小说。其实这篇文章就是教大家怎么白嫖,在这个网站广告铺天盖地的环境下,我们想单纯的的看会小说也成了一个问题,所以我们就可使用爬虫技术,把小说爬下来,就不用看烦人的广告了。话不多说,开整...
02
什么是爬虫
对于这种问题,我们可以直接去百度百科看介绍,网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。看看,百度百科介绍的多么好,多么通俗易懂。
网络爬虫有什么用呢?网络爬虫是大数据行业获取数据的核心工具。没有网络爬虫自动地、不分昼夜地、高智能地在互联网上爬去免费的数据,那些大数据相关的公司恐怕要少四分之三。现在的爬虫基本上都是围绕web网页的,所以我们爬虫就是根据网页地址(URL)爬取网页内容,网页地址就是我们在浏览器中输入的网站链接。例如我们常用的百度:https://www.baidu.com,这就是一个URL。URL专业的叫法是统一资源定位符,格式如下:
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
URL 的格式主要由前个三部分组成:
- protocol:第一部分就是协议,例如百度使用的就是https协议;
- hostname[:port]:第二部分就是主机名(还有端口号为可选参数),一般网站默认的端口号为80,例如百度的主机名就是www.baidu.com,这个就是服务器的地址;
- path:第三部分就是主机资源的具体地址,如目录和文件名等。
所以有了URL,我们就可以去指定位置获取我们想要的数据信息。有了数据,我们需要对数据进行分析,所以就引出了爬虫另一项必备技能:审查元素。
我们在浏览器浏览的每一个网页,我们都可以查看其网页源码,也就是HTML。这些HTML就决定了网站的原始容貌。这里就不介绍HTML的具体使用了,想要学习的网络资源很多。比如我们使用Chrome 浏览器,在谷歌首页我们右键点击检查(其他浏览器不同,这里不做介绍),在右侧就会出现一大堆代码,这些代码,就叫做HTML。
浏览器就是作为客户端从服务器端获取信息,然后将信息解析,并展示给我们。所以我们根据HTML就可以分析出网页内容。好啦,基本的基础知识已经知道了,下面就开始我们的实践吧!!!
03
爬虫实例
- 爬取网站小说介绍
这里的实例,我们下载文字内容,也就是下载一本小说。小说网站,我们选择的新笔趣阁。链接:https://www.xsbiquge.com/。
这个网站只支持在线浏览,不支持小说打包下载,所以我们就可以使用我们的爬虫技术下载一本小说,解决不能本地看小说的问题。由于本人不看小说,所以直接去小说排行榜选了第一名,《三国之他们非要打种地的我》。名字就很有吸引力嘛!!!!
2. 相关技术介绍
本次教程使用两种语言进行开发,分别是Golang和Python。Golang我们使用自带的HTTP库进行网站获取和google自己维护的库x/net/html进行网页数据解析。Python我们使用requests库进行网页获取,使用BeautifulSoup进行网页数据解析。
2.1 golang.org/x/net/html
x/net/html是google自己维护的库,主要可以帮助我们解析网页数据,我们只需要导入golang.org/x/net/html这个包就可以,使用方法也挺简单,就不在这里做具体介绍,可以到GO圣经:https://godoc.org/golang.org/x/net/html#Parse
进行学习,里面有样例,很好懂。
2.2 BeatifulSoup
BeautifulSoup是python的一个第三方库,主要帮助我们解析网页数据。我们要使用这个工具,需要提前进行安装,在cmd中,我们使用pip命令进行安装,命令如下:
pip install beautifulsoup4
安装好之后,我们还需要安装lxml,这是解析HTML需要用到的依赖:
pip install lxml
这就可以使用了,具体的学习教程可以到官方中文教程:
https://beautifulsoup.readthedocs.io/zh_CN/latest/
2.3 requests
requests库很强大,我们可以使用requests库进行网页爬取。requests库是第三方库,需要我们自己安装。安装简单,使用pip命令即可安装:
pip install requests
requests库的github地址:
https://github.com/requests/requests
具体学习可以按demo进行学习。
3. 爬虫步骤
总共就分为三步:
- 第一步:发起请求,我们需要明确如何发起HTTP请求,获取到数据。
- 第二步:解析数据,获取到的数据乱七八糟的,我们需要提取出我们想要的数据。
- 第三步:保存数据:将我们想要的数据,保存下载。
4. 开始实践
备注:
我已将我整个项目上发到我的github上面了。Golang代码GitHub地址如下:
https://github.com/sunsong2020/Golang_Dream/tree/master/reptile_go
Python代码Github地址如下:
https://github.com/sunsong2020/Golang_Dream/tree/master/reptile_py
4.1 获取网页
我们完全按照步骤来,第一步,我们先获取网页数据。因为我们要获取整章的小说,所以我们先去查看小说目录,并查看它的网页源码,如下:
解析网页在下一节进行讲解。我们先获取目录网页,然后在获取文章网页,这样章节title和内容就对应起来了。小说第一章查看如下:
知道了这两个网页的地址,我们就可以获取网页了。
Golang可以使用标准库net/http进行网页获取,样例如下:
代码语言:javascript复制resp,err := http.Get(target)
if err!=nil{
fmt.Println("get err http",err)
return err
}
直接调用Get方法即可,target就是要获取的网页URL。
Python可以使用requests库进行获取网页,样例如下:
代码语言:javascript复制req = requests.get(url=target)
req.encoding = 'utf-8'
代码语言:javascript复制html = req.text
直接调用get方法即可,target即URL,req.tex就说获取的网站内容,可以print打印一下看的更清楚。这里设置了编码方式为utf-8,本次爬取的网站本身就是utf-8编码,所以不需要转换,如果爬取的网站是GBK编码的就需要进行编码转换。
4.2 解析网页
获取到了网页,下面我们就开始进行解析网页。Golang我们使用x/net/html这个库,使用go get指令就可以获取到第三方库。代码样例如下:
代码语言:javascript复制doc,err := html.Parse(resp.Body)
if err != nil{
fmt.Println("html parse err",err)
return err
}
parseList(doc)
直接调用Parse方法,将网页数据放入进去,返回一个解析树(文档元素)的根作为*Node,之后我们就可以以深度优先顺序处理每个节点标签。
我们先对文章目录进行分析,提取出文章标题和对应文章内容的URL参数。具体分析,我们需要查看部分网页源码如下:
我们可以看到,文章title都在a标签下,href属性存放的是URL参数。,而且他们都属于div标签,id等于list,这样我们就可以定位位置了。所以根据这个特点我们可以进行分析提取,Golang语言代码如下:
代码语言:javascript复制//找到文章列表
func parseList(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "div"{
for _,a := range n.Attr{
if a.Key == "id" && a.Val == "list"{
listFind = true
parseTitle(n)
break
}
}
}
if !listFind{
for c := n.FirstChild;c!=nil;c=c.NextSibling{
parseList(c)
}
}
}
//获取文章头部
func parseTitle(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "a"{
for _, a := range n.Attr {
if a.Key == "href"{
//获取文章title
for c:=n.FirstChild;c!=nil;c=c.NextSibling{
buf.WriteString(c.Data "n")
}
url := a.Val
target := server url // 得到 文章url
everyChapter(target)
num--
}
}
}
if num <= 0{
return
}else {
for c := n.FirstChild;c!=nil;c=c.NextSibling{
parseTitle(c)
}
}
}
这里我们提取到了文章的title,我们要实现的是title和内容对应起来,所以没获取一个title就可以去获取每一篇文章内容,这里依然需要去分析网页源码,这里网页URL,我们可以根据根URL 获取到的URL参数进行合并出的新URL就是内容所在位置,分析网页源码如下:
我们可以看到文章的内容都在div标签下,id等于content,所以只需要拿取其中数据就是文章内容。
因此使用Golang可以写出代码如下:
代码语言:javascript复制//获取每个章节
func everyChapter(target string) {
fmt.Println(target)
resp,err := http.Get(target)
if err!=nil{
fmt.Println("get err http",err)
}
defer resp.Body.Close()
doc,err := html.Parse(resp.Body)
find = false
parse(doc)
代码语言:javascript复制//解析文章
func parse(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "div"{
for _,a := range n.Attr{
if a.Key == "id" && a.Val == "content" {
find = true
parseTxt(&buf,n)
break
}
}
}
if !find{
for c := n.FirstChild;c!=nil;c=c.NextSibling{
parse(c)
}
}
}
//提取文字
func parseTxt(buf *bytes.Buffer,n *html.Node) {
for c:=n.FirstChild;c!=nil;c=c.NextSibling{
if c.Data != "br"{
buf.WriteString(c.Data "n")
}
}
}
好啦这就提取文章成功了,一步步分析标签即可。下面介绍Pyhton写法,因为Python有BeautifulSoup4这个库,代码量就很少了,看起来也很通俗易懂,Python代码样例如下:
代码语言:javascript复制import requests # requests 包 进入url访问
from bs4 import BeautifulSoup
from tqdm import tqdm #tqdm是一个快速、可扩展的python进度条,可以在python长循环中添加一个进度提示信息
def get_content(target):
req = requests.get(url=target)
req.encoding = 'utf-8'
html = req.text
bs = BeautifulSoup(html,'lxml')
texts = bs.find('div',id='content')
content = texts.text.strip().split('xa0'*4)
return content
if __name__ == '__main__':
server = "https://www.xsbiquge.com"
target = "https://www.xsbiquge.com/91_91600/"
book_name = '三国之他们非要打种地的我.txt'
req = requests.get(url=target)
req.encoding = 'utf-8'
html = req.text
characters_name = BeautifulSoup(html,'lxml')
characters = characters_name.find('div',id='list') # 寻找标签
# 提出a标签
characters = characters.find_all('a')
#进行循环读取章节
for character in tqdm(characters):
# 得到href属性
url = server character.get('href')
# 获取章节名字
character_name = character.string
# 获取文章
content = get_content(url)
get_content函数用于获取每一章节的内容;直接调用find_all方法就可以找出所以标签a的内容,提取出所有的题目,代码量少,又很简单,不过缺少了底层分析,对于新手来说,用Golang写一篇会更加加深对网页分析的理解。
4.3 保存数据
数据已经解析好了,只差最后一步了,我们马上就可以看到心爱的小说啦,白激动,马上就好。这里我们使用一个记事本保存文章就可以。不过要注意格式的问题,要不导出的文字,看起来很别扭的。写入文件时,写完文章要换行换行,遇到br标签,就要进行换行,这样的文章才能有一个耐看的排版,Golang代码样例如下:
代码语言:javascript复制 text,err := os.Create("三国之他们非要打种地的我.txt")
if err!=nil{
fmt.Println("get create file err",err)
}
file := strings.NewReader(buf.String())
file.WriteTo(text)
}
代码语言:javascript复制//提取文字
func parseTxt(buf *bytes.Buffer,n *html.Node) {
for c:=n.FirstChild;c!=nil;c=c.NextSibling{
if c.Data != "br"{
buf.WriteString(c.Data "n")
}
}
}
使用bytes.Buffer进行数据保存,遇到br标签就换行,很完美。
使用Python进行数据保存也是这样,代码如下:
代码语言:javascript复制with open(book_name,'a',encoding='utf-8') as f:
f.write(character_name)
f.write('n')
f.write('n'.join(content))
f.write('n')
好啦这回所有的代码都写好了,就等待运行啦,运行结果片段如下:
看,没有了广告,文章还存储到了本地,终于可以安心看小说啦!!!
04
结尾
好啦,一个简单的爬虫做好了!!!你们学会了没。如果没有学会,直接查看我的源码,相信你一定可以看懂的。我已将我整个项目上发到我的github上面了。Golang代码GitHub地址如下:
https://github.com/sunsong2020/Golang_Dream/tree/master/reptile_go
Python代码Github地址如下:
https://github.com/sunsong2020/Golang_Dream/tree/master/reptile_py