【Go學習】go 原生庫net/http傳送 GET POST 請求
阿新 • • 發佈:2020-12-27
go基礎語法,一直沒怎麼練習,語法這東西不用就忘,工作中多多少少還接觸到爬蟲,索性強制用go來寫,寫爬蟲不是目的,目的是為了練習go語法,強化記憶。
畢竟go處理一些字串和Python
比,我認為還是十分繁瑣的,而且爬蟲瓶頸是限於網路和目標地址響應,所以在寫爬蟲效能上,go不一定勝過Python。
注意以下示例皆要以編寫測試程式的方式書寫,檔名以_test.go
字尾結尾。
GET請求
package http_demo import ( "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "testing" ) func Requests(url string) (content string, err error) { // 建立 http 客戶端 client := &http.Client{} // 建立請求 req, _ := http.NewRequest("GET", url, nil) // GET 請求攜帶查詢引數 q := req.URL.Query() q.Add("auth_key", "sky_kk") q.Add("another_thing", "foo & bar") req.URL.RawQuery = q.Encode() //req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36") // 設定請求頭 req.Header.Set("User-Agent", "test") // 傳送請求 resp, err := client.Do(req) if err != nil { // 格式化返回錯誤 return "", errors.New(fmt.Sprintf("請求出錯 %s", err)) } // 最後關閉連線 defer resp.Body.Close() // 讀取內容 body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", errors.New(fmt.Sprintf("解析內容出錯 %s", err)) } //fmt.Println(string(body)) return string(body), nil } func TestReqUrl(t *testing.T) { url := "https://httpbin.org/get" content, err := Requests(url) if err != nil { fmt.Println("請求錯誤", err) return } t.Log(fmt.Sprintf("結果 \n %s", content)) }
POST 請求
POST 請求攜帶引數的方式,根據Content-Type
不同 有多種請求方式
POST from請求
package http_demo import ( "errors" "fmt" "io/ioutil" "net/http" "net/url" "testing" ) func PostReq(targetUrl string) (content string, err error) { // 最簡單的傳送 post請求 攜帶 form引數 resp, err := http.PostForm(targetUrl, url.Values{"username": {"wxy"}, "password": {"wxy666"}}) // 相當於這種 //req.Header.Set("Content-Type", "multipart/form-data") if err != nil { return "", errors.New(fmt.Sprintf("請求錯誤 %s", err)) } fmt.Println(fmt.Sprintf("響應狀態 %s", resp.Status)) // 記得關閉客戶端 defer resp.Body.Close() // 讀取內容 body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", errors.New(fmt.Sprintf("讀取內容錯誤 %s", err)) } content = string(body) return content, nil } func TestReq3(t *testing.T) { targetUrl := "https://httpbin.org/post" content, err := PostReq(targetUrl) if err != nil { fmt.Println("請求錯誤", err) return } fmt.Println(content) }
POST JSON 方式請求
package http_demo import ( "bytes" "errors" "fmt" "io/ioutil" "net/http" "net/url" "strings" "testing" ) // post form請求 務必設定 Content-Type func ReqPostForm(targetUrl string) (content string, err error) { // 建立 http 客戶端 client := &http.Client{} form := url.Values{} form.Add("ln", "ln222") form.Add("ip", "1.1.1.1") form.Add("ua", "ua123") // 建立請求 req, _ := http.NewRequest("POST", targetUrl, strings.NewReader(form.Encode())) req.Header.Set("User-Agent", "test") req.Header.Set("Content-Type", "application/x-www-form-urlencoded") // 傳送請求 resp, err := client.Do(req) if err != nil { // 格式化返回錯誤 return "", errors.New(fmt.Sprintf("請求出錯 %s", err)) } // 最後關閉連線 defer resp.Body.Close() // 讀取內容 body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", errors.New(fmt.Sprintf("解析內容出錯 %s", err)) } return string(body), nil } // post json方式請求 func ReqPostJson(targetUrl string) (content string, err error) { var jsonStr = []byte(`{"title":"this is a title", "cate": 1}`) req, _ := http.NewRequest("POST", targetUrl, bytes.NewBuffer(jsonStr)) req.Header.Set("X-Custom-Header", "myvalue") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", errors.New(fmt.Sprintf("請求出錯 %s", err)) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) return string(body), nil } func TestReqPost(t *testing.T) { targetUrl := "https://httpbin.org/post" c1, _ := ReqPostForm(targetUrl) t.Log(fmt.Sprintf("\nfrom表單返回: \n %s", c1)) c2, _ := ReqPostJson(targetUrl) t.Log(fmt.Sprintf("\nJson請求返回: \n %s", c2)) }