golang 获取重定向信息

时间:2021-9-28     作者:smarteng     分类: Go语言


原因

  1. 爬虫获取百度查询结果的时候,为了获取网页真实地址,而百度跳转页面的其中一种方式就是302重定向(redirect),那么针对这种方式,go语言默认自动执行redirect的,所以没办法使用get请求获取真实地址
  2. 对于第一条描述的,在302重定向的时候,真实地址在response的location中
  3. go语言中,默认是支持10层redirect,所以,除非跳出,否则会redirect 到第10层才退出,然而也是可以自定义的

自定义redirect规则示例


package main
import (
    "fmt"
    "net/http"
    "errors"
)

func main() {
    url:="https://www.baidu.com/link?url=IIZcBDQ9FSkK8wRluFkNAxjf4a7VDwHH0kFqGazjEAFGRDdnxe0HqQRdSocksxbbrpMjo7PTBeGjgnmf0aYOqN7ld6dXDBVO_jMYS16Yuy7CI5M_TMysMLpmFhF4CEjGjXOEYvjL_r9Hgz2-4jwsoa"

    client := &http.Client{
        CheckRedirect: myCheckRedirect,
    }

    req, err := http.NewRequest("GET", url, nil)
    if err != nil{

    }
    resp, err := client.Do(req)
    if err != nil{

    }
    fmt.Println(resp.Status)
    respUrl,err := resp.Location()
    if err != nil{

    }
    fmt.Println(respUrl.String())
}
func myCheckRedirect(req *http.Request, via []*http.Request) error {
    //自用,将url根据需求进行组合
    if len(via) >= 1 {
        return errors.New("stopped after 1 redirects")
    }
    return nil
}

创建client的时候,指定CheckRedirect为自己重写的myCheckRedirect方法,指定“len(via) >= 1”,即第一次redirect就停止
然后,就可以正常获取到百度搜索到的真实url了

http模块默认跟随重定向

使用http.Get,当遇到301跳转时,会获取重定向后的内容

res, err := http.Get(url)
if err != nil {
logrus.Error(err)
return nil, err
}

//这里的状态是200
fmt.println(res.StatusCode)

获取页面重定向的location

为了获取重定向的location,要重新实现一个http.Client,例子如下:

baseHost := "https://www.example.com/"
client := &http.Client{
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
    },
}

res, err := client.Get(baseHost)
if err != nil {
    return baseHost
}

if res.StatusCode != 301 {
    return baseHost
}

return res.Header.Get("Location")

在Client的字段中,有一个 CheckRedirect,此字段就是用来控制重定向的函数,如果没有定义此字段的话,将会使用默认的 defaultCheckRedirect 方法。

默认的转发策略是最多转发10次。

在转发的过程中,某一些包含安全信息的Header,比如AuthorizationWWW-AuthenticateCookie等,如果转发是跨域的,那么这些Header不会复制到新的请求中。

http的重定向判断会默认处理以下状态码的请求:

301 (Moved Permanently)

302 (Found)

303 (See Other)

307 (Temporary Redirect)

308 (Permanent Redirect)

301、302和303请求将会改用Get访问新的请求,而307和308会使用原有的请求方式。

那么,我们如何去控制重定向的次数,甚至是禁止重定向呢?这里其实就需要我们自己去实现一个CheckRedirect函数了,首先我们来看看默认的defaultCheckRedirect方法:

func defaultCheckRedirect(req *Request, via []*Request) error {
   if len(via) >= 10 {
       return errors.New("stopped after 10 redirects")
   }
   return nil
}

第一个参数req是即将转发的request,第二个参数 via是已经请求过的requests。可以看到其中的逻辑是判断请求过的request数量,大于等于10的时候返回一个error,这也说明默认的最大重定向次数为10次,当此函数返回error时,即是重定向结束的时候。

所以如果需要设置重定向次数,那么复制一份这个函数,修改函数名字和其中if判断的数字,然后在生成Client时设定到Client即可:

client := &http.Client{
   CheckRedirect: yourCheckRedirect,
}

或者:

client := &http.Client{}
client.CheckRedirect = yourCheckRedirect

禁止重定向则可以把判断数字修改为0。最好相应地修改errors中提示的信息。

标签: redirect