实现一个go语言的简单爬虫来爬取CSDN博文(一)
来源:互联网 发布:js null 编辑:程序博客网 时间:2024/05/23 10:52
http://blog.csdn.net/tyBaoErGe/article/details/50375802?hmsr=studygolang.com&utm_medium=studygolang.com&utm_source=studygolang.com
前言
如何实现一个爬虫系统或则简单的小脚本?一般是定义一个入口页面,然后一个页面会有其他页面的URL,于是从当前页面获取到这些URL加入到爬虫的抓取队列中,然后进入到新页面后再递归的进行上述的操作,其实说来就跟深度遍历或广度遍历一样。
golang由于其编译速度很快,而且对并发(goroutine)的天然支持,配合chan的协程处理,可以很好地实现一个稳定高效的爬虫系统.
用到的包
完全不借助第三方的框架,通过go sdk的标准库来实现一个爬虫应用,主要用到的包
- net/http 标准库里内建了对http协议的支持,实现了一个http client,可以直接通过其进行get,post等请求
- strings 不像java的String是一个引用类型,go语言中的字符串类型是一个内建的基础类型, 而且go语言默认只支持UTF-8编码,strings包实现了一些简单的针对utf-8字符串操作的函数
- regexp go sdk中的正则表达式包
- io/ioutil io处理的工具包
- encoding/xml 解析xml的包
channel机制
Golang在并发设计方面参考了C.A.R Hoare的CSP,即Communicating Sequential Processes并发模型理论。 CSP模型的消息传递在收发消息进程间包含了一个交会点,即发送方只能在接收方准备好接收消息时才能发送消息。
golang在其并发实现中,主要是用channel来实现通信的。其中channel包括两种,缓冲的channel和非缓冲的channel.
- 缓冲的channel:保证往缓冲中存数据先于对应的取数据,简单说就是在取的时候里面肯定有数据,否则就因取不到而阻塞.
- 非缓冲的channel:保证取数据先于存数据,就是保证存的时候肯定有其他的goroutine在取,否则就因放不进去而阻塞。
Go Channel基本操作语法
Go Channel的基本操作语法如下:
- 1
- 2
- 3
- 4
- 5
不带缓冲的Channel兼具通信和同步两种特性,适合协调多个routines。
for/select的基本操作
我们在使用select时很少只是对其进行一次evaluation,我们常常将其与for {}结合在一起使用,并选择适当时机从for{}中退出。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
range操作
Golang中的for range除了可以迭代一些集合类型还可以来循环从channel中取数据,当channel中无数据时便阻塞当前循环。
- 1
- 2
- 3
- 4
goroutine
Go语言通过goroutine提供了对于并发编程的非常清晰直接的支持,但goroutine是Go语言运行库的功能,不是操作系统提供的功能,goroutine不是用线程实现的.goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。所以它非常廉价,我们可以很轻松的创建上万个goroutine,但它们并不是被操作系统所调度执行
- 1
- 2
实现CSDN博文爬虫
由于实现的爬虫功能简单,所以所有代码均再main包下完成.
首先我们需要在main包下声明一个全局的urlchannel用来同步开启的多个routines在某个页面获取的<a>
标签的href属性
- 1
声明在html文档中获取<a>
的正则表达式
- 1
入口函数main
当进入main函数时,将启动一个goroutine来从入口url=”http:/blog.csdn.net”开始爬取(Spy函数)页面内容分析<a>
标签
接下来通过for range urlChannel来循环取出爬取到的<a>
标签中的href属性,并再次开启一个新的goroutine来爬取这个href属性对应的html文档内容
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Spy函数
由于每个爬取goroutine都是调用Spy函数来分析一个url对应的html文档,所以需要在函数开始就defer 一个匿名函数来处理(recover)可能出现的异常(panic),防止异常导致程序终止,defer执行的函数会在当前函数执行完成后结果返回前执行,无论该函数是panic的还是正常执行
- 1
- 2
- 3
- 4
- 5
由于go内建了对http协议的支持,可以直接通过http包下的http.Get或则http.Post函数来请求url.但由于大部分网站对请求都有防范DDOS等的限制,需要自定义请求的header,设置代理服务器(CSDN好像对同一IP的请求平率限制并不严格,iteye亲测很严格,每分钟上万会被封住IP)等操作,可以使用http包下的http.NewRequest(method, urlStr string, body io.Reader) (*Request, error)函数,然后通过Request的Header对象设置User-Agent,Host等,最后调用http包下内置的DefaultClient对象的Do方法完成请求.
当拿到服务器响应后(*Response)通过ioutil包下的工具函数转换为string,找出文档中的<a>
标签 分析出href属性,存入urlChannel中.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
随机伪造User-Agent
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
解析<a>
元素
<a>
可以当做一份xml文档(只有一个a为根节点的简单xml)来解析出href/HREF属性,通过go标准库中xml.NewDecoder来完成
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
总结
通过以上代码,一个简单的网络爬虫就实现了.而且对goroutine和range的配合使用基本就了解了.但如你所见,goroutine的运行机制和chan的设计原理绝非以上寥寥数句代码就可窥见其真面目.
go语言实现的简单爬虫来爬取CSDN博文
- 实现一个go语言的简单爬虫来爬取CSDN博文(一)
- 实现一个go语言的简单爬虫来爬取CSDN博文(一)
- 实现一个go语言的简单爬虫来爬取CSDN博文(一)
- Go语言 简单的爬虫示例(1)
- go 语言实现一个简单的 web 服务器
- 一个简单的 go 语言 hello world.
- Go语言实现简单的留言本
- Go语言实现简单的文件服务器
- go语言实现的简单web服务器
- Go语言 实现简单的 Set
- Go语言实现简单的web服务器
- Go语言进行web开发(一) 搭建一个简单的web服务器
- go 实现一个简单的UUID生成器
- 一个简单的爬虫(一)
- 一个Go语言接口和多操作系统实现的简单例子
- 一个简单的爬虫的实现
- PHP实现的一个简单的爬虫
- go语言实现爬虫采集联想词
- PHP表单之单选和复选框(简单笔记)
- 香港大学深度学习课件笔记(1)
- Mac使用中遇到的问题及解决
- Description Resource Path Location Type Project configuration is not up-to-d
- Spring(SpringMVC)工作机制?
- 实现一个go语言的简单爬虫来爬取CSDN博文(一)
- HTTP必知必会
- 使用xshell上传下载文件
- 如何添加bootstrap到Angular工程
- TR中ABP线OP20增加防错提示
- Spring框架之IoC容器—概览
- Angular增加国际化支持
- 网易云音乐 ubuntu 版左上角的图标 处理
- 10-23-C++面试综合题