目錄
一诡蜓、服務(wù)端
二烫饼、客戶(hù)端
一猎塞、服務(wù)端
什么是Web的服務(wù)端?個(gè)人理解:網(wǎng)站杠纵,API等荠耽。
Go語(yǔ)言里面提供了一個(gè)完善的net/http包,通過(guò)http包可以很方便的就搭建起來(lái)一個(gè)可以運(yùn)行的Web服務(wù)比藻。同時(shí)使用這個(gè)包能很簡(jiǎn)單地對(duì)Web的路由铝量,靜態(tài)文件,模版银亲,cookie等數(shù)據(jù)進(jìn)行設(shè)置和操作慢叨。
拉起一個(gè)http服務(wù)僅需要簡(jiǎn)單的幾行,定義路由务蝠,定義方法即可:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello world!")
}
func main() {
http.HandleFunc("/", hello) //設(shè)置訪問(wèn)的路由
err := http.ListenAndServe(":8080", nil) //設(shè)置監(jiān)聽(tīng)的端口
checkErr(err)
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
···
我們嘗試增加簡(jiǎn)單的傳參交互:
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開(kāi)源框架已經(jīng)逐漸興起拍谐,感興趣的小伙伴可以自行了解。因?yàn)閷?duì)于本章節(jié)來(lái)講此非重點(diǎn)馏段,所以我們?cè)谶@里僅進(jìn)行簡(jiǎn)單的web服務(wù)功能介紹轩拨。
二、客戶(hù)端
Web客戶(hù)端院喜,如B/S架構(gòu)的瀏覽器亡蓉,而對(duì)于滲透行業(yè)的需求,爬蟲(chóng)喷舀,yes砍濒!
借助http包實(shí)現(xiàn)一個(gè)最基本的例子淋肾,以剛剛搭建的服務(wù)端為例,發(fā)起get請(qǐng)求:
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))
}
簡(jiǎn)單的http請(qǐng)求可以借助http來(lái)實(shí)現(xiàn)梯影,但是更多的請(qǐng)求是需要校驗(yà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))
}
我們可以進(jìn)入該組件查看其功能简识,分別對(duì)應(yīng)連接壽命管理,重定向控制感猛,cookie對(duì)象管理和超時(shí)設(shè)置七扰。
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
但是,該組件依然不能滿(mǎn)足我們對(duì)header頭的苛刻設(shè)置陪白。
- Request
http提供了NewRequest方法來(lái)生成Request颈走,此方法中做了一些生成Request的默認(rèn)設(shè)置,函數(shù)簽名為:
func NewRequest(method, url string, body io.Reader) (*Request, error)
參數(shù)中method和url兩個(gè)是必備參數(shù)咱士,而body參數(shù)立由,在使用沒(méi)有body的請(qǐng)求方法時(shí),傳入nil即可序厉。
設(shè)置完成后锐膜,借助client組建的Do()方法執(zhí)行。
req, err := NewRequest("GET", "https://127.0.0.1:8080", nil)
resp, err := client.Do(req)
寫(xiě)到這里的時(shí)候弛房,我他喵心疼已經(jīng)崩了道盏,python他不香嘛,requests庫(kù)簡(jiǎn)直強(qiáng)無(wú)敵文捶。
emmmm荷逞,綜合對(duì)比一下,go語(yǔ)言的爬蟲(chóng)代碼量和代碼難度(或者是設(shè)置項(xiàng)之多)可能要比python多個(gè)幾倍不止粹排,尤其是Go語(yǔ)言的數(shù)據(jù)處理也比python相對(duì)復(fù)雜种远。優(yōu)點(diǎn)嘛,其并發(fā)機(jī)制決定著go的性能會(huì)更高顽耳,此外坠敷,go還有一點(diǎn)就是編譯為二進(jìn)制文件的穩(wěn)定性斧抱,這個(gè)絕非python可以比擬的渐溶。
如果個(gè)人看法的話辉浦,非編程專(zhuān)業(yè)寫(xiě)爬蟲(chóng)還是python吧茎辐,當(dāng)然也包括我宪郊,至少目前的態(tài)度是這樣的掂恕。
更多更詳細(xì)的設(shè)置這里安利一篇比較棒的文章:http://www.reibang.com/p/4e53d4727152
既然學(xué)都學(xué)了弛槐,我們嘗試完成一個(gè)小任務(wù)懊亡,完成一個(gè)疫情實(shí)時(shí)監(jiān)控小程序乎串!
api的話店枣,尋找一個(gè)實(shí)時(shí)更新的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("【疫情實(shí)時(shí)報(bào)告】")
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("累計(jì)治愈:",regexp.MustCompile(`"cured":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("累計(jì)死亡:",regexp.MustCompile(`"died":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("累計(jì)確診:",regexp.MustCompile(`"confirmed":"(.*?)"`).FindAllStringSubmatch(summaryDataIn, -1)[0][1])
fmt.Println("更新時(shí)間:",time.Now().Format("2006-01-02 15:04:05"))
}
func checkErr(err error) {
if err != nil {
fmt.Println(err.Error())
return
}
}
我們將源碼編譯為二進(jìn)制文件叹誉,運(yùn)行效果如下:
END
日常吐槽時(shí)間到,撇開(kāi)爬蟲(chóng)功能的優(yōu)劣钧唐,我想說(shuō)的是我從沒(méi)想拿Golang替代python匠襟,但是它相對(duì)簡(jiǎn)單的語(yǔ)法高效的性能,至少在WEB滲透方向的需求里酸舍,它在一定程度上可以替代C/C艸。