您的位置:首页 > 编程语言 > Go语言

爬虫基础|Go语言中的网络请求库

2019-06-01 16:15 429 查看

​大家好,我是杨小爽,上一篇讲了go语言也可以写爬虫,介绍了go语言的基础语法。

 

上一篇文章:

爬虫基础|爬虫语言的新选择?

 

今天我们来学习go语言中的网络请求库,官方标准库net/http,net/http提供了HTTP客户端和服务端的实现,类似python中的urllib3。

 

 下面我们以例子来学习。

 

1、发送请求

先要导入net/http:

[code]import (
"net/http"
)

然后,使用Get请求来获取某个网页:

[code]// 获取go语言中文网标准库页面源码
resp, err := http.Get("https://studygolang.com/pkgdoc")

请求后返回的resp是一个Response结构体指针地址,err是一个错误。go中很明确的一点是几乎每执行一个操作都会返回错误信息。

除了Get请求外,还有其他请求方式:

[code]// 语法1:func Post(url string, bodyType string, body io.Reader) (resp *Response, err error)
resp, err := http.Post("https://example.com", "image/jpeg", &buf)
// 语法2:func PostForm(url string, data url.Values) (resp *Response, err error)
resp, err := http.PostForm("https://example.com",url.Values{"key": {"Value"}, "id": {"123"}})

语法1中bodyType为Post数据的类型,body是post的数据,比如上传一个文件或发送一个图片都可以采用这种方式。

语法2中data会被编码为请求的主体,然后post请求给知道url,比如用于上传表单等。

 

2、响应内容

我们可以读取服务器响应的内容:

[code]resp, err := http.Get("https://example.com")
if err != nil {
panic(err)
}
defer resp.Body.Close() // 读取内容后要关闭响应的主体
body, err:= ioutil.ReadAll(resp.Body) // 读取内容
if err != nil {
panic(err)
}
fmt.Printf("%s", body) // 以字符串形式打印

从Response中读取出的响应是字节切片,如果需要以字符串进行解析,可以使用string()来显式转换,然后再解析。

python的requests包会自动解码来自服务器的内容,而go的net/http并不行,需要我们自己根据实际编码进行转换,这其实也是设计原则的影响,可以稍微吐槽下。

 

3、自定义请求头

在net/http中添加请求头,需要先建立一个client:

[code]client := &http.Client{} // 建立client
req, err := http.NewRequest("GET", "https://example.com", nil)
if err != nil {
panic(err)
}
// 添加自定义请求头
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
resp, err := client.Do(req)

 

4、响应状态码

发起请求得到响应后,很多时候需要查看响应状态码,来判断请求情况:

[code]resp, err := http.Get("https://www.example.com")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", resp.StatusCode) // 打印状态码,如200
fmt.Printf("%s\n", resp.Status) //打印状态码跟原因短语,如200 ok

当然,net/http也内置了状态码查询对象:

[code]resp, err := http.Get("https://www.example.com")
if err != nil {
panic(err)
}
// 具体的状态码对象可以查询文档,里面会有详细介绍
if resp.StatusCode==http.StatusOk {
fmt.Printf("%s\n", resp.StatusCode)
}

 

5、响应头

除了可以添加请求头外,我们还可以获取响应头:

[code]resp, err := http.Get("https://www.example.com")
if err != nil {
panic(err)
}
header := resp.Header  //获取得到的是Header结构体
fmt.Printf("%s", header)
// map[Connection:[keep-alive] Content-Type:[text/html; charset=UTF-8] Date:[Sat, 01 Jun 2019 02:22:41 GMT] Etag:["d3ae175b24ac305beeccb7aa5bf4bb773d501f9a"] Server:[openresty] Set-Cookie:[_xsrf=2|4ed4f6b5|6823e2054a31f6477e7a8cb2f1ec81d8|1559355761; Path=/] Vary:[User-Agent, Accept-Encoding]]

Header结构体是一个map:map[string]string。

 

6、Cookie

如果返回的响应头部带有”Set-Cookie“,便可以去获取它:

[code]resp, err := http.Get("https://www.example.com")
if err != nil {
panic(err)
}
cookies := resp.Cookies() // 获取得到的是[]*Cookie
fmt.Printf("%s", cookies)
// [_xsrf=2|752b7518|68acb15c5ac7128b7c31b1107bd64837|1559356249; Path=/]

Cookie是一个结构体,下面是它的定义方式:

[code]type Cookie struct {
Name       string
Value      string
Path       string
Domain     string
Expires    time.Time
    RawExpires string
MaxAge   int
Secure   bool
HttpOnly bool
Raw      string
Unparsed []string // 未解析的“属性-值”对的原始文本
}

如果要了解更加详细的获取cookie的方式,请查看文档。

 

7、超时

你可以设置请求的停止响应时间,即设置超时时间:

[code]// 设置超时时间20秒
var timeout time.Duration
timeout = 20
client := http.Client{Timeout: timeout} // Timeout为零值表示不设置超时

注意一点,该超时限制包括连接时间、重定向和读取回复主体的时间。

 

8、代理

go中有两种设置代理的方式。

第一种,利用http.Transport:

[code]urli := url.URL()
urlProxy, _ := urli.Parse("http://127.0.0.1:5555")
client := &http.Client{
       Transport: &http.Transport{
           Proxy: http.ProxyURL(urlProxy),
       }
}
resp, err := client.Get("https://www.example.com")

第二种,通过环境变量来设置代理:

[code]os.Setenv("HTTP_PROXY", "http://127.0.0.1:5555")
os.Setenv("HTTPS_PROXY", "https://127.0.0.1:5555")
client := &http.Client{}
resp, err := client.Get("https://www.example.com")

 

9、结尾语

以上介绍的8点便是爬虫中会经常遇到的问题,如果有个性化的需求,建议自己翻阅文档,Go语言中文网的标准库翻译就还不错,下面贴地址,感兴趣的可以看看。

[code]// Go语言中文网
https://studygolang.com/pkgdoc

最后,谢谢大家观看,如果有建议或疑问,请在微信公众号后台发消息联系我。

欢迎关注

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: