昨天接到一個派發下來的小任務,爬取某個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 協議》,轉載必須註明作者和本文連結