就这?我花了一个小时找问题?记一次憨批行为长长记性
昨天接到一个派发下来的小任务,爬取某个 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 协议》,转载必须注明作者和本文链接
推荐文章: