就这?我花了一个小时找问题?记一次憨批行为长长记性

昨天接到一个派发下来的小任务,爬取某个 URL 中 N 个子类下 N 天的每天 24 小时的数据,最开始打算用 PHP 实现,想着也有段时间没写 Go 了,遂决定使用 Go 实现。思路非常简单,就是发起一个 CURL 请求,带上参数,将获取到 json 进行分组包装返回给算法部门,就是这样的一个简单的东西,花了我一个小时。

这个 Api 接收两个参数 guid(筛选的类型别)pubtime(筛选的时间,时间粒度为h),缺一不可,并且需要设置 Header

就这?我花了一个小时?就为了个空格?记一次憨批行为长长记性

Postman 的带参请求结果,HttpCode 为 200,数据也正常返回
就这?我花了一个小时?就为了个空格?记一次憨批行为长长记性
先来看看十分钟梭出来的第一版

func main(){
    stationList := [...] string { "xxx", "xxx"}
    dateList := genDate(20, 24)
    for _, stationCode := range stationList {
        for _, date := range dateList {
            url := "http://xxx.com/api/v1/air_all/station_realtime?pubtime=" + date + "&guid" + stationCode
            GetUrl(url, date, stationCode)
        }
    }
}

//    四月-生成指定天数的指定小时时间
func genDate(dateNum int, hourNum int) []string {
    var publishTimeList []string
    startTime := time.Date(2020,03, 31, 24, 00, 00, 00, time.Local).Unix()

    publishTimeList = append(publishTimeList, time.Unix(startTime, 0).Format("2006-01-02 15:04:05"))    //    将初始日期append
    var (
        nextDate time.Time
        thisDate time.Time
        nextHour time.Time
        thisHour time.Time
        )
    thisDate = time.Unix(startTime - 86400, 0)
    for i := 1; i <= dateNum; i++ {
        //    获取每一天
        nextDate = time.Unix(thisDate.Unix() + 86400, 0)    //增加一天
        thisDate = nextDate
        thisHour = time.Unix(thisDate.Unix(), 0)    //    当前日
        for j := 1; j <= hourNum; j++ {
            nextHour = time.Unix(thisHour.Unix() + 3600, 0)    //增加一小时
            publishTimeList = append(publishTimeList, nextHour.Format("2006-01-02 15:04:05"))    //    将初始日期append
            thisHour = nextHour
        }
    }
    return publishTimeList
}

func GetUrl(url string) {

    client := &http.Client{}
    req,_ := http.NewRequest(http.MethodGet, url,nil)
    req.Header.Add("Authorization","xxxxx")
    resp,_ := client.Do(req)
    body, _ := ioutil.ReadAll(resp.Body)

    fmt.Println(req.URL.String(), resp, string(body))

}

代码很简单,应该很好懂,但是 print 返回的 resp 如下

就这?我花了一个小时找问题?记一次憨批行为长长记性
😯❓❓❓❓
我可以理解你 401,说明未授权也就是 Header 头的 Authorization 没有带上
于是我去尝试了这个 URL 对于参数问题的返回

就这?我花了一个小时找问题?记一次憨批行为长长记性

不带时间的并且 guid 是错误的时候是 441

就这?我花了一个小时找问题?记一次憨批行为长长记性
不带分类的时候是 450

就这?我花了一个小时找问题?记一次憨批行为长长记性
不带时间,guid 正确的话会返回正常结果 (最新时间)

441,200,450,401 都有了,400 呢❓❓❓❓
因为我们都知道 400 是 Bad Request,基本上也就是参数问题嘛,于是我在 terminal 中 print 出了拼接的 URL,然后直接复制去 Postman

就这?我花了一个小时找问题?记一次憨批行为长长记性
没有问题,正常返回
当时就非常纳闷了,把参数一个个打出来看,又去检查发送 REQUEST 的方式是否正确 (现在想来或许当时是钻牛角尖了没静下来想为啥会 400),在开始这个小任务大约四十分钟 (一半时间都在找 400 的问题) 的时候,我决定写个接口来测试下看看到底是传递了什么东西过来 (之前因为懒得写就把这个方案放在最后了).

接收请求的地方用的 Node.Js,非常简单,分别打印出 url、header、query
就这?我花了一个小时找问题?记一次憨批行为长长记性

Go 这边的 Res 显示请求成功,返回了 200
就这?我花了一个小时找问题?记一次憨批行为长长记性

Node 这边,请求是过来了的
就这?我花了一个小时找问题?记一次憨批行为长长记性

尝试带个参试试,对比 url 和获取到的 query 可以看到,没有问题
就这?我花了一个小时找问题?记一次憨批行为长长记性

那我们结合实际请求来看看,Go 部分显示 400,Node 部分没有任何输出
就这?我花了一个小时找问题?记一次憨批行为长长记性

就这?我花了一个小时找问题?记一次憨批行为长长记性

带上 guid 就能够获取到😓
就这?我花了一个小时找问题?记一次憨批行为长长记性
就这?我花了一个小时找问题?记一次憨批行为长长记性

这么看起来应该就是 date 出了问题,打印看起来是一个平平无奇的字符串
就这?我花了一个小时找问题?记一次憨批行为长长记性
等等,空格❓❓❓❓
我尝试去掉空格,直接传入 2020-04-01

就这?我花了一个小时找问题?记一次憨批行为长长记性

就这?我花了一个小时找问题?记一次憨批行为长长记性
😓😓😓😓
看来就是这个空格的问题了,我就尝试不直接拼接在 URL,而改为使用 query 了

func GetUrl(url string, date string, stationCode string) {

    client := &http.Client{}
    req,_ := http.NewRequest(http.MethodGet, url,nil)
    q := req.URL.Query()

    q.Add("pubtime", date)
    q.Add("guid", stationCode)

    req.URL.RawQuery = q.Encode()

    req.Header.Add("Authorization","xxxx")
    resp,_ := client.Do(req)
    body, _ := ioutil.ReadAll(resp.Body)

    fmt.Println(req.URL.String(), resp, string(body))

}

Node 这边接收成功
就这?我花了一个小时找问题?记一次憨批行为长长记性
调整为需要的地址以后即成功
就这?我花了一个小时找问题?记一次憨批行为长长记性

总结:事后回想起来真的是憨批行为,为了偷懒直接去拼接 url,忘记了去特殊字符转义,希望大家记住我的教训,不要浪费时间

本作品采用《CC 协议》,转载必须注明作者和本文链接
Reflection.
讨论数量: 5

:joy:我也遇到过这个比较憨的问题

5年前 评论
NearTheShore (楼主) 5年前

嗯 这事我也遇到过。哈哈 :joy:

5年前 评论

写 PHP 的时候,对方.net 调我的接口犯过你这个错误,当时需要参数加密,也是因为空格被转换加密了,哈哈哈,你还好只用了一个小时,当时那家伙缠着我缠了一下午,除了空格,传参的时候还有 null 和空字符串的问题也比较常见。。。

4年前 评论
NearTheShore (楼主) 4年前

你这也是爬取天气数据吗.

4年前 评论
NearTheShore (楼主) 4年前