使用Volley请求Yahoo财经历史数据遇403及JSON转换错误求助
解决Yahoo财经API 403 Forbidden错误(Volley/Retrofit)
问题原因
Yahoo财经的API现在加强了反爬机制,会验证请求的User-Agent等请求头标识。浏览器和Postman会自动添加符合规范的请求头,而Volley/Retrofit默认的请求头缺少这些必要标识,导致服务器返回403拒绝访问。
Volley解决方案
修改你的StringRequest,重写getHeaders()方法,添加模拟浏览器的请求头:
private fun getStockHistoricalData(){ val queue = VolleySingleton.getInstance(this) val query = "https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=1635962336&period2=1667498336&interval=1d&events=history&includeAdjustedClose=true" val request = object : StringRequest(Request.Method.GET, query, { response -> println("response = $response") }, { error -> println("Error ${parseVolleyError(error)}") } ) { // 添加必要请求头 override fun getHeaders(): MutableMap<String, String> { val headers = HashMap<String, String>() headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" headers["Accept"] = "*/*" headers["Accept-Language"] = "en-US,en;q=0.9" return headers } } request.setShouldCache(false) queue.addToRequestQueue(request) }
Retrofit解决方案
如果使用Retrofit,需要给OkHttpClient添加拦截器注入请求头:
// 构建带请求头的OkHttpClient val okHttpClient = OkHttpClient.Builder() .addInterceptor { chain -> val modifiedRequest = chain.request().newBuilder() .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36") .header("Accept", "*/*") .header("Accept-Language", "en-US,en;q=0.9") .build() chain.proceed(modifiedRequest) } .build() // 初始化Retrofit val retrofit = Retrofit.Builder() .baseUrl("https://query1.finance.yahoo.com/") .client(okHttpClient) .addConverterFactory(ScalarsConverterFactory.create()) // 接口返回CSV文本,用Scalars转换器处理 .build() // 定义API接口 interface YahooFinanceApi { @GET("v7/finance/download/AAPL") suspend fun getStockData( @Query("period1") period1: Long, @Query("period2") period2: Long, @Query("interval") interval: String, @Query("events") events: String, @Query("includeAdjustedClose") includeAdjustedClose: Boolean ): String }
补充说明
- 你遇到的
Value Forbidden...错误是因为误用JsonObjectRequest,服务器返回的是"Forbidden"文本而非JSON,改用StringRequest或Retrofit的文本转换器即可避免解析失败。 - 该接口仅支持GET请求,无需改用POST方法。
内容的提问来源于stack exchange,提问作者M_droid
相关产品推荐
相关产品推荐

