Go入门系列(十一)WEB
目录
一、服务端
二、客户端
一、服务端
什么是Web的服务端?个人理解:网站,API等。
Go语言里面提供了一个完善的net/http包,通过http包可以很方便的就搭建起来一个可以运行的Web服务。同时使用这个包能很简单地对Web的路由,静态文件,模版,cookie等数据进行设置和操作。
拉起一个http服务仅需要简单的几行,定义路由,定义方法即可:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello) //设置访问的路由
err := http.ListenAndServe(":8080", nil) //设置监听的端口
checkErr(err)
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
···
我们尝试增加简单的传参交互:
func hello(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if len(r.Form["name"])>0 {
fmt.Fprintf(w, "Hello %s",r.Form["name"][0])
}else {
fmt.Fprintf(w, "WHo are u?")
}
}
Golang Web开源框架已经逐渐兴起,感兴趣的小伙伴可以自行了解。因为对于本章节来讲此非重点,所以我们在这里仅进行简单的web服务功能介绍。
二、客户端
Web客户端,如B/S架构的浏览器,而对于渗透行业的需求,爬虫,yes!
借助http包实现一个最基本的例子,以刚刚搭建的服务端为例,发起get请求:
func main() {
resp, err := http.Get("http://127.0.0.1:8080")
checkErr(err)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
简单的http请求可以借助http来实现,但是更多的请求是需要校验header头的。
所以我们如果需要设置其它参数,就需要用到其组件了。
- Client
基本用法的话和http十分相似:
func main() {
client := &http.Client{}
resp, err := client.Get("http://127.0.0.1:8080")
checkErr(err)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
我们可以进入该组件查看其功能,分别对应连接寿命管理,重定向控制,cookie对象管理和超时设置。
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
但是,该组件依然不能满足我们对header头的苛刻设置。
- Request
http提供了NewRequest方法来生成Request,此方法中做了一些生成Request的默认设置,函数签名为:
func NewRequest(method, url string, body io.Reader) (*Request, error)
参数中method和url两个是必备参数,而body参数,在使用没有body的请求方法时,传入nil即可。
设置完成后,借助client组建的Do()方法执行。
req, err := NewRequest("GET", "https://127.0.0.1:8080", nil)
resp, err := client.Do(req)
写到这里的时候,我他喵心疼已经崩了,python他不香嘛,requests库简直强无敌。
emmmm,综合对比一下,go语言的爬虫代码量和代码难度(或者是设置项之多)可能要比python多个几倍不止,尤其是Go语言的数据处理也比python相对复杂。优点嘛,其并发机制决定着go的性能会更高,此外,go还有一点就是编译为二进制文件的稳定性,这个绝非python可以比拟的。
如果个人看法的话,非编程专业写爬虫还是python吧,当然也包括我,至少目前的态度是这样的。
更多更详细的设置这里安利一篇比较棒的文章:https://www.jianshu.com/p/4e53d4727152
既然学都学了,我们尝试完成一个小任务,完成一个疫情实时监控小程序!
api的话,寻找一个实时更新的web界面即可,如:https://voice.baidu.com/act/newpneumonia/newpneumonia
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://voice.baidu.com/act/newpneumonia/newpneumonia", nil)
checkErr(err)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0")
req.AddCookie(&http.Cookie{Name: "BAIDUID",Value: "00A1B1EC9FF50D09E8740C2BB49A2120"})
resp, err := client.Do(req)
checkErr(err)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
summaryDataIn := regexp.MustCompile(`"summaryDataIn":{.*?}`).FindAllStringSubmatch(string(body), -1)[0][0]
fmt.Println("【疫情实时报告】")
fmt.Println("现有确诊:",regexp.MustCompile(`"curConfirm":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("现有疑似:",regexp.MustCompile(`"unconfirmed":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("现有重症:",regexp.MustCompile(`"icu":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("累计治愈:",regexp.MustCompile(`"cured":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("累计死亡:",regexp.MustCompile(`"died":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("累计确诊:",regexp.MustCompile(`"confirmed":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("更新时间:",time.Now().Format("2006-01-02 15:04:05"))
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
我们将源码编译为二进制文件,运行效果如下:
END
日常吐槽时间到,撇开爬虫功能的优劣,我想说的是我从没想拿Golang替代python,但是它相对简单的语法高效的性能,至少在WEB渗透方向的需求里,它在一定程度上可以替代C/C艹。