Go入门系列

Go入门系列(十一)WEB

2020-03-19  本文已影响0人  RabbitMask

目录
一、服务端
二、客户端

一、服务端

什么是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头的。
所以我们如果需要设置其它参数,就需要用到其组件了。

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头的苛刻设置。

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艹。

上一篇下一篇

猜你喜欢

热点阅读