Java Yahoo Finance HTTP响应代码:401用于URL

Java Yahoo Finance HTTP响应代码:401用于URL,java,Java,我试图创建一个程序,从Yahoo Finance下载历史数据,然后根据主类中输入的股票符号显示去年的历史数据 由于某种原因,当我试图运行我的程序时,我总是得到一个401代码。如果我复制并粘贴到浏览器中,401错误中显示的URL会告诉我要去哪里 我不知道我做错了什么 下面是我的StockDownloader类代码: import java.util.GregorianCalendar; import java.util.Calendar; import java.util.ArrayList; i

我试图创建一个程序,从Yahoo Finance下载历史数据,然后根据主类中输入的股票符号显示去年的历史数据

由于某种原因,当我试图运行我的程序时,我总是得到一个401代码。如果我复制并粘贴到浏览器中,401错误中显示的URL会告诉我要去哪里

我不知道我做错了什么

下面是我的StockDownloader类代码:

import java.util.GregorianCalendar;
import java.util.Calendar;
import java.util.ArrayList;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;


public class StockDownloader
{
    public static final int DATE = 0;
    public static final int OPEN = 1;
    public static final int HIGH = 2;   
    public static final int LOW = 3;
    public static final int CLOSE = 4;
    public static final int VOLUME = 6;
    public static final int ADJCLOSE = 5;

    private ArrayList<GregorianCalendar> dates;
    private ArrayList<Double> opens;
    private ArrayList<Double> highs;
    private ArrayList<Double> lows; 
    private ArrayList<Double> closes;
    private ArrayList<Integer> volumes;
    private ArrayList<Double> adjCloses;

    public StockDownloader (String symbol)
    {
        dates = new ArrayList<GregorianCalendar>();
        opens = new ArrayList<Double>();
        highs = new ArrayList<Double>();
        lows = new ArrayList<Double>();
        closes = new ArrayList<Double>();
        volumes = new ArrayList<Integer>();
        adjCloses = new ArrayList<Double>();

        //https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=2WsiR.p1KtI
        String url = "https://query1.finance.yahoo.com/v7/finance/download/"+symbol+"?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=2WsiR.p1KtI";
        try
        {
            URL yhoofin = new URL(url);
            URLConnection data = yhoofin.openConnection();
            Scanner input = new Scanner(data.getInputStream());
            if(input.hasNext())//skip line...it's just the header
                input.nextLine();

            //start reading data
            while(input.hasNextLine())
            {
            String line = input.nextLine();
            //TODO- connec tdata to the correct ArrayList
            System.out.println(line);
            }
        }

        catch (Exception e)
        {
            System.err.println(e);
        }

    }
    public ArrayList<GregorianCalendar> getDates()
    {
        return dates;
    }

    /*public ArrayList<Double> get Opens()
    {
    }*/

}

请帮助

401错误代码表示用户未经授权。再看一次,如果你确信你所做的一切都是正确的,但问题仍然存在,那么看看这个。这使得使用Yahoo Finance API更容易。

看起来Yahoo已经改变了访问Finance API的方式。您需要将cookie添加到URL连接。已经更改了你的代码,它对我有效

public class StockDownloader {
    public static final int DATE = 0;
    public static final int OPEN = 1;
    public static final int HIGH = 2;
    public static final int LOW = 3;
    public static final int CLOSE = 4;
    public static final int VOLUME = 6;
    public static final int ADJCLOSE = 5;

    private ArrayList<GregorianCalendar> dates;
    private ArrayList<Double> opens;
    private ArrayList<Double> highs;
    private ArrayList<Double> lows;
    private ArrayList<Double> closes;
    private ArrayList<Integer> volumes;
    private ArrayList<Double> adjCloses;

    private String finalCrumb;

    public StockDownloader(String symbol) {
        dates = new ArrayList<GregorianCalendar>();
        opens = new ArrayList<Double>();
        highs = new ArrayList<Double>();
        lows = new ArrayList<Double>();
        closes = new ArrayList<Double>();
        volumes = new ArrayList<Integer>();
        adjCloses = new ArrayList<Double>();

        try {

            // Hit the below URL to get the cookies and the crumb value to access the finance API
            String mainURL = "https://uk.finance.yahoo.com/quote/"+symbol+"/history";
            Map<String, List<String>> setCookies = setCookies(mainURL);
            // https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=2WsiR.p1KtI

            // will need to append the crumb in the end to the below URL to have the actual crumb rather than the hardcoded one
            String url = "https://query1.finance.yahoo.com/v7/finance/download/" + symbol
                    + "?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=" + finalCrumb;
            URL yhoofin = new URL(url);
            URLConnection data = yhoofin.openConnection();

            // get the list of Set-Cookie cookies from response headers
            List<String> cookies = setCookies.get("Set-Cookie");
            if (cookies != null) {
                for (String c : cookies)
                    data.setRequestProperty("Cookie", c);
            }
            Scanner input = new Scanner(data.getInputStream());
            if (input.hasNext())// skip line...it's just the header
                input.nextLine();

            // start reading data
            while (input.hasNextLine()) {
                String line = input.nextLine();
                // TODO- connec tdata to the correct ArrayList
                System.out.println(line);
            }
            input.close();
        }

        catch (Exception e) {
            System.err.println(e);
        }

    }

    // This method extracts the crumb and is being called from setCookies() method
    private String searchCrumb(URLConnection con) throws IOException {
        String crumb = null;
        InputStream inStream = con.getInputStream();
        InputStreamReader irdr = new InputStreamReader(inStream);
        BufferedReader rsv = new BufferedReader(irdr);

        Pattern crumbPattern = Pattern.compile(".*\"CrumbStore\":\\{\"crumb\":\"([^\"]+)\"\\}.*");

        String line = null;
        while (crumb == null && (line = rsv.readLine()) != null) {
            Matcher matcher = crumbPattern.matcher(line);
            if (matcher.matches())
                crumb = matcher.group(1);
        }
        rsv.close();
        System.out.println("Crumb is : "+crumb);
        return crumb;
    }


    // This method extracts the cookies from response headers and passes the same con object to searchCrumb()
    // method to extract the crumb and set the crumb value in finalCrumb global variable
    private Map<String, List<String>> setCookies(String mainUrl) throws IOException {
        // "https://finance.yahoo.com/quote/SPY";
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        URL url = new URL(mainUrl);
        URLConnection con = url.openConnection();
        finalCrumb = searchCrumb(con);
        for (Map.Entry<String, List<String>> entry : con.getHeaderFields().entrySet()) {
            if (entry.getKey() == null || !entry.getKey().equals("Set-Cookie"))
                continue;
            for (String s : entry.getValue()) {
                map.put(entry.getKey(), entry.getValue());
                System.out.println(map);
            }
        }

        return map;

    }

    public ArrayList<GregorianCalendar> getDates() {
        return dates;
    }

}
公共类股票下载程序{
公共静态最终整数日期=0;
公共静态最终int OPEN=1;
公共静态最终int高=2;
公共静态最终int低=3;
公共静态最终int CLOSE=4;
公共静态最终整数卷=6;
公共静态最终int ADJCLOSE=5;
私人ArrayList日期;
私人ArrayList打开;
私人ArrayList高点;
私人ArrayList lows;
私人ArrayList关闭;
私有ArrayList卷;
私有数组列表;
私有字符串finalCrumb;
公共股票下载器(字符串符号){
日期=新的ArrayList();
打开=新建ArrayList();
highs=新的ArrayList();
lows=新的ArrayList();
closes=新建ArrayList();
卷=新的ArrayList();
adjCloses=newarraylist();
试一试{
//点击下面的URL获取cookies和crump值以访问finance API
字符串mainURL=”https://uk.finance.yahoo.com/quote/“+符号+”/历史记录”;
Map setCookies=setCookies(mainURL);
// https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=2WsiR.p1KtI
//将需要在下面的URL末尾添加面包屑,以获得实际的面包屑,而不是硬编码的面包屑
字符串url=”https://query1.finance.yahoo.com/v7/finance/download/“+符号
+“?周期1=1467352800,周期2=149888800,周期=1d,事件=history&crumb=“+finalCrumb;
URL yhoofin=新URL(URL);
URLConnection data=yhoofin.openConnection();
//从响应头获取集合Cookie的列表
List cookies=setCookies.get(“Set Cookie”);
如果(cookies!=null){
用于(字符串c:cookies)
setRequestProperty(“Cookie”,c);
}
扫描仪输入=新扫描仪(data.getInputStream());
if(input.hasNext())//跳过行…它只是标题
input.nextLine();
//开始读取数据
while(input.hasNextLine()){
String line=input.nextLine();
//TODO-将tdata连接到正确的ArrayList
系统输出打印项次(行);
}
input.close();
}
捕获(例外e){
系统错误println(e);
}
}
//此方法提取碎屑,并从setCookies()方法调用
私有字符串searchCramp(URLConnection con)引发IOException{
字符串crump=null;
InputStream inStream=con.getInputStream();
InputStreamReader irdr=新的InputStreamReader(流内);
BufferedReader rsv=新的BufferedReader(irdr);
Pattern-crumbPattern=Pattern.compile(“.*\'crumpstore\”:\\{\'crump\”:\”([^\“]+)\“\\}.*);
字符串行=null;
而(crumb==null&(line=rsv.readLine())!=null){
Matcher Matcher=rumbpattern.Matcher(线);
if(matcher.matches())
crumb=matcher.组(1);
}
rsv.close();
System.out.println(“Crumb是:“+Crumb”);
返回面包屑;
}
//此方法从响应头中提取cookie,并将相同的con对象传递给searchCrumb()
//方法提取碎屑并在finalCrumb全局变量中设置碎屑值
私有映射集cookies(字符串mainUrl)引发IOException{
// "https://finance.yahoo.com/quote/SPY";
Map Map=newhashmap();
URL=新URL(mainUrl);
URLConnection con=url.openConnection();
finalCrumb=搜索碎屑(con);
对于(Map.Entry:con.getHeaderFields().entrySet()){
if(entry.getKey()==null | |!entry.getKey().equals(“设置Cookie”))
继续;
对于(字符串s:entry.getValue()){
map.put(entry.getKey(),entry.getValue());
系统输出打印项次(map);
}
}
返回图;
}
公共数组列表getDates(){
返回日期;
}
}
我们已经获得了很多关于财务API的详细信息


试一试!

您查过代码401的含义吗?这告诉您什么?如果我的答案对您有所帮助,请随意将其标记为答案!
public class StockDownloader {
    public static final int DATE = 0;
    public static final int OPEN = 1;
    public static final int HIGH = 2;
    public static final int LOW = 3;
    public static final int CLOSE = 4;
    public static final int VOLUME = 6;
    public static final int ADJCLOSE = 5;

    private ArrayList<GregorianCalendar> dates;
    private ArrayList<Double> opens;
    private ArrayList<Double> highs;
    private ArrayList<Double> lows;
    private ArrayList<Double> closes;
    private ArrayList<Integer> volumes;
    private ArrayList<Double> adjCloses;

    private String finalCrumb;

    public StockDownloader(String symbol) {
        dates = new ArrayList<GregorianCalendar>();
        opens = new ArrayList<Double>();
        highs = new ArrayList<Double>();
        lows = new ArrayList<Double>();
        closes = new ArrayList<Double>();
        volumes = new ArrayList<Integer>();
        adjCloses = new ArrayList<Double>();

        try {

            // Hit the below URL to get the cookies and the crumb value to access the finance API
            String mainURL = "https://uk.finance.yahoo.com/quote/"+symbol+"/history";
            Map<String, List<String>> setCookies = setCookies(mainURL);
            // https://query1.finance.yahoo.com/v7/finance/download/IBM?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=2WsiR.p1KtI

            // will need to append the crumb in the end to the below URL to have the actual crumb rather than the hardcoded one
            String url = "https://query1.finance.yahoo.com/v7/finance/download/" + symbol
                    + "?period1=1467352800&period2=1498888800&interval=1d&events=history&crumb=" + finalCrumb;
            URL yhoofin = new URL(url);
            URLConnection data = yhoofin.openConnection();

            // get the list of Set-Cookie cookies from response headers
            List<String> cookies = setCookies.get("Set-Cookie");
            if (cookies != null) {
                for (String c : cookies)
                    data.setRequestProperty("Cookie", c);
            }
            Scanner input = new Scanner(data.getInputStream());
            if (input.hasNext())// skip line...it's just the header
                input.nextLine();

            // start reading data
            while (input.hasNextLine()) {
                String line = input.nextLine();
                // TODO- connec tdata to the correct ArrayList
                System.out.println(line);
            }
            input.close();
        }

        catch (Exception e) {
            System.err.println(e);
        }

    }

    // This method extracts the crumb and is being called from setCookies() method
    private String searchCrumb(URLConnection con) throws IOException {
        String crumb = null;
        InputStream inStream = con.getInputStream();
        InputStreamReader irdr = new InputStreamReader(inStream);
        BufferedReader rsv = new BufferedReader(irdr);

        Pattern crumbPattern = Pattern.compile(".*\"CrumbStore\":\\{\"crumb\":\"([^\"]+)\"\\}.*");

        String line = null;
        while (crumb == null && (line = rsv.readLine()) != null) {
            Matcher matcher = crumbPattern.matcher(line);
            if (matcher.matches())
                crumb = matcher.group(1);
        }
        rsv.close();
        System.out.println("Crumb is : "+crumb);
        return crumb;
    }


    // This method extracts the cookies from response headers and passes the same con object to searchCrumb()
    // method to extract the crumb and set the crumb value in finalCrumb global variable
    private Map<String, List<String>> setCookies(String mainUrl) throws IOException {
        // "https://finance.yahoo.com/quote/SPY";
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        URL url = new URL(mainUrl);
        URLConnection con = url.openConnection();
        finalCrumb = searchCrumb(con);
        for (Map.Entry<String, List<String>> entry : con.getHeaderFields().entrySet()) {
            if (entry.getKey() == null || !entry.getKey().equals("Set-Cookie"))
                continue;
            for (String s : entry.getValue()) {
                map.put(entry.getKey(), entry.getValue());
                System.out.println(map);
            }
        }

        return map;

    }

    public ArrayList<GregorianCalendar> getDates() {
        return dates;
    }

}