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

昨天接到一个派发下来的小任务,爬取某个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:我也遇到过这个比较憨的问题

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

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

4年前 评论

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

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

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

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

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!