目錄
一、服務(wù)端
二、客戶端
一、服務(wù)端
什么是Web的服務(wù)端?個人理解:網(wǎng)站,API等。
Go語言里面提供了一個完善的net/http包,通過http包可以很方便的就搭建起來一個可以運行的Web服務(wù)。同時使用這個包能很簡單地對Web的路由,靜態(tài)文件,模版,cookie等數(shù)據(jù)進行設(shè)置和操作。
拉起一個http服務(wù)僅需要簡單的幾行,定義路由,定義方法即可:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello) //設(shè)置訪問的路由
err := http.ListenAndServe(":8080", nil) //設(shè)置監(jiān)聽的端口
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開源框架已經(jīng)逐漸興起,感興趣的小伙伴可以自行了解。因為對于本章節(jié)來講此非重點,所以我們在這里僅進行簡單的web服務(wù)功能介紹。
二、客戶端
Web客戶端,如B/S架構(gòu)的瀏覽器,而對于滲透行業(yè)的需求,爬蟲,yes!
借助http包實現(xiàn)一個最基本的例子,以剛剛搭建的服務(wù)端為例,發(fā)起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來實現(xiàn),但是更多的請求是需要校驗header頭的。
所以我們?nèi)绻枰O(shè)置其它參數(shù),就需要用到其組件了。
- 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))
}
我們可以進入該組件查看其功能,分別對應(yīng)連接壽命管理,重定向控制,cookie對象管理和超時設(shè)置。
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
但是,該組件依然不能滿足我們對header頭的苛刻設(shè)置。
- Request
http提供了NewRequest方法來生成Request,此方法中做了一些生成Request的默認設(shè)置,函數(shù)簽名為:
func NewRequest(method, url string, body io.Reader) (*Request, error)
參數(shù)中method和url兩個是必備參數(shù),而body參數(shù),在使用沒有body的請求方法時,傳入nil即可。
設(shè)置完成后,借助client組建的Do()方法執(zhí)行。
req, err := NewRequest("GET", "https://127.0.0.1:8080", nil)
resp, err := client.Do(req)
寫到這里的時候,我他喵心疼已經(jīng)崩了,python他不香嘛,requests庫簡直強無敵。
emmmm,綜合對比一下,go語言的爬蟲代碼量和代碼難度(或者是設(shè)置項之多)可能要比python多個幾倍不止,尤其是Go語言的數(shù)據(jù)處理也比python相對復(fù)雜。優(yōu)點嘛,其并發(fā)機制決定著go的性能會更高,此外,go還有一點就是編譯為二進制文件的穩(wěn)定性,這個絕非python可以比擬的。
如果個人看法的話,非編程專業(yè)寫爬蟲還是python吧,當(dāng)然也包括我,至少目前的態(tài)度是這樣的。
更多更詳細的設(shè)置這里安利一篇比較棒的文章:http://www.itdecent.cn/p/4e53d4727152
既然學(xué)都學(xué)了,我們嘗試完成一個小任務(wù),完成一個疫情實時監(jiān)控小程序!
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("現(xiàn)有確診:",regexp.MustCompile(`"curConfirm":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("現(xiàn)有疑似:",regexp.MustCompile(`"unconfirmed":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("現(xiàn)有重癥:",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
日常吐槽時間到,撇開爬蟲功能的優(yōu)劣,我想說的是我從沒想拿Golang替代python,但是它相對簡單的語法高效的性能,至少在WEB滲透方向的需求里,它在一定程度上可以替代C/C艸。