1. 程式人生 > 實用技巧 >【Go學習】go 原生庫net/http傳送 GET POST 請求

【Go學習】go 原生庫net/http傳送 GET POST 請求

go基礎語法,一直沒怎麼練習,語法這東西不用就忘,工作中多多少少還接觸到爬蟲,索性強制用go來寫,寫爬蟲不是目的,目的是為了練習go語法,強化記憶。
畢竟go處理一些字串和Python比,我認為還是十分繁瑣的,而且爬蟲瓶頸是限於網路和目標地址響應,所以在寫爬蟲效能上,go不一定勝過Python。

注意以下示例皆要以編寫測試程式的方式書寫,檔名以_test.go字尾結尾。

GET請求

github地址

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請求

github地址

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 方式請求

github地址

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))

}