Golang模拟网页请求

博客内容提及无编码,但无更多关键信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

func httpRequest(url string) (*http.Response, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	// 设置请求投
	request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
	request.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
	request.Header.Add("Connection", "keep-alive")
	request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")

	client := http.Client{}
	// Do sends an HTTP request and returns an HTTP response
	// 发起一个HTTP请求,返回一个HTTP响应
	return client.Do(request)
}


// 根据URL提取
func Fetch(url string) ([]byte, error) {
	resp, err := httpRequest(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("wrong status code: %d of %s", resp.StatusCode, url)
	}
	r := bufio.NewReader(resp.Body)
	e := determineEncoding(r)
	utf8Reader := transform.NewReader(r,  e.NewDecoder())
	return ioutil.ReadAll(utf8Reader)
}

// 编码识别
func determineEncoding(
	r *bufio.Reader) encoding.Encoding{
	bytes, err:=r.Peek(1024)
	if err!=nil {
		log.Printf("fetch error : %v\n", err )
		// 如果没有识别到,返回一个UTF-8(默认)
		return unicode.UTF8
	}
	e, _, _ := charset.DetermineEncoding(
		bytes, "")
	return e
}

无编码

func httpRequest(url string) (*http.Response, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
	request.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
	request.Header.Add("Connection", "keep-alive")
	request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")

	client := http.Client{}
	return client.Do(request)
}
// 根据指定的URL进行数据抓取
func Fetch(url string)([]byte,error)  {
	resp, err := httpRequest(url)
	if err != nil{
		return nil,err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("wrong status code: %d of %s", resp.StatusCode, url)
	}
	return ioutil.ReadAll(resp.Body)

}

 
### 使用 Golang 实现 Nginx 类似的反向代理和负载均衡 为了实现类似于 Nginx 的反向代理和负载均衡功能,可以通过 Go 语言中的 `net/http` 和 `httputil` 包来构建。这些包提供了创建 HTTP 客户端和服务端所需的基础工具。 #### 反向代理的实现 通过使用 `httputil.NewSingleHostReverseProxy()` 方法可以轻松设置单主机反向代理: ```go package main import ( "fmt" "log" "net/http" "net/http/httputil" "net/url" ) func main() { targetURL, err := url.Parse("http://backend-server.com") // 后端服务地址 if err != nil { log.Fatal(err) } proxy := httputil.NewSingleHostReverseProxy(targetURL) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { r.URL.Host = targetURL.Host r.URL.Scheme = targetURL.Scheme r.Header.Set("X-Forwarded-Host", r.Header.Get("Host")) r.Host = targetURL.Host proxy.ServeHTTP(w, r) }) fmt.Println("Starting reverse proxy on :8080...") err = http.ListenAndServe(":8080", nil) if err != nil { log.Fatal(err) } } ``` 此代码片段展示了如何配置一个简单的反向代理服务器[^1]。 #### 负载均衡器的实现 对于基本的轮询调度算法,可以在多个目标服务器之间循环分配请求。这里展示了一个简易版的基于轮询方式的选择逻辑: ```go type Backend struct { URL string Counter int } var backends []Backend = []Backend{ {URL: "http://server1.example.com"}, {URL: "http://server2.example.com"}, } func getNextServer() (*url.URL, error) { for i := range backends { backends[i].Counter++ serverUrl, _ := url.Parse(backends[i%len(backends)].URL) return serverUrl, nil } return nil, fmt.Errorf("no available servers") } // 修改之前的main函数以支持多台后端服务器 func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { nextServer, err := getNextServer() if err != nil { http.Error(w, "No backend servers available.", http.StatusServiceUnavailable) return } proxy := httputil.NewSingleHostReverseProxy(nextServer) r.URL.Host = nextServer.Host r.URL.Scheme = nextServer.Scheme r.Host = nextServer.Host proxy.ServeHTTP(w, r) }) fmt.Println("Load Balancer running at port :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } ``` 上述例子实现了最基本的轮询机制来进行负载分发[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值