近来想用Go做一点事,以减轻工作上的负担。
我的工作中有几项工作是每日重复的,大致内容:
1、将数据收集到Excel中。
2、收集齐后,将Excel中的部分数据提交到办公系统中(网页上操作)。
3、再将提交过后的审批号码提取出来,存入Excel中。
我现在有两个问题:
1、现在,上面的第一步Excel操作,Go中不知有何现成的库,若没有,我有个效率不高的办法。这个问题倒还不算急。
2、第二个问题比较着急。向办公系统提交数据,得先登录。我的操作步骤如下:
2.1、先访问办公系统首页,获取Session的Cookie。
2.2、进行登录数据提交,将刚才获取的这个Session的Cookie一并提交上去。
2.3、进行业务数据提交。
我现在的问题卡在上面的2.2步了。
测试期间,登录操作完后,我进入业务逻辑提交页面,可系统反馈登陆超时。后抓包中看到:
1、在我登录验证成功后,服务器返回了一个30X状态码。
2、http包直接帮我转入了登录成功后的页面,返回的Body是跳转后的页面代码。我的User-Agent在http帮我跳转时改动了,改为了"Go 1.1 package http"了。
我的登录代码逻辑大概是这样:
```go
import (
"net/http"
"log"
)
c := &http.Client{}
// sUrl 是登录验证页面地址
// v中是登录帐号、密码等内容
req, err := http.NewRequest("POST", sUrl, v)
// 将之前文字描述 2.1 步骤中的Session Cookie一并发送到服务端
for _, v := range aCookies {
req.AddCookie(v)
}
// 一系列Header设置省略
// 其中下面这条是将User-Agent设置为我正常操作办公系统时使用的浏览器的标识
req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)")
// 执行登录操作
res, err := c.Do(req)
if nil != err {
log.Fatal(err)
}
// 将返回的Cookie保留下来,下次操作使用
aCookies = res.Cookies()
```
我认为User-Agent的改动是导致我下面一步进入业务逻辑提交页面提示登录超时的原因。不知我的想法是否正确,还有问题如何解决呢?
主题的内容,下面代码实现了两个功能:
1、始终使用自定义的浏览器标识。
2、每次请求中,发送和接收Cookie。
```go
import (
"net/http"
"net/http/cookiejar"
"net/url"
)
type MyTransport struct {
Transport RoundTripper
}
func (t *MyTransport) transport() http.RoundTripper {
if nil != t.Transport {
return t.Transport
}
return http.DefaultTransport
}
func (t *MyTransport) RoundTrip(req *http.Request) (http.Response, error) {
req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)")
return t.transport().RoundTrip(req)
}
var c Client
type Client {
http.Client
}
func NewClient() *Client {
t := &MyTransport{}
jar, err := cookiejar.New(nil)
if nil != err {
log.Fatal(err)
}
return &Client{ Transort: t, Jar: jar }
}
func main() {
c = NewClient()
// sUrl 是登录验证页面地址
sUrl := "http://localhost/login"
// v中是登录帐号、密码等内容
v := url.Values{
"username": "test",
"password": "test",
}
req, err := http.NewRequest("POST", sUrl, v)
// 执行登录操作
res, err := c.Do(req) if nil != err {
log.Fatal(err)
}
}
```
#6
更多评论