Open URI - Invalid URI Error, encoding/escaping no

2019-09-17 14:28发布

I'm building out a YahooFinance Api and keep hitting a brick wall when trying to use open URI.

Code:

uri = ("http://ichart.finance.yahoo.com/table.csv?s=#{URI.escape(code)}&a=#{start_month}&b=#{start_day}&c=#{start_year}&d=#{end_month}&e=#{end_day}&f=#{end_year}&g=d&ignore=.csv")
    puts "#{uri}"
    conn = open(uri)

Error:

`split': bad URI(is not URI?): http://ichart.finance.yahoo.com/table.csv?s=%255EIXIC&a=00&b=1&c=1994&d=09&e=14&f=2014&g=d&ignore=.csv} (URI::InvalidURIError)

I have tried URI.unescape(code) which outputs code as ^IXIC, as well as leaving any URI methods out and code will come through as %5EIXIC.

After reading around on stack overflow, I've tried both of these methods to no avail:

uri = URI.parse(URI.encode(url.strip))

safeurl = URI.encode(url.strip)

Even after looking through the code for another ruby yahoo-finance gem, here, I can't seem to find a solution. Any help is greatly appreciated. Thanks

EDIT: I am able to use open(uri) when I manually enter in the url in single quotes. Do double quotes, (used for inserting ruby objects), play a role here?

3条回答
冷血范
2楼-- · 2019-09-17 14:47

The code works for me though I don't think the API endpoint is correct:

[1] pry(main)> uri = URI("http://ichart.finance.yahoo.com/table.csv?s=%255EIXIC&a=00&b=1&c=1994&d=09&e=14&f=2014&g=d&ignore=.csv")
=> #<URI::HTTP:0x007fd63a2fff40 URL:http://ichart.finance.yahoo.com/table.csv?s=%255EIXIC&a=00&b=1&c=1994&d=09&e=14&f=2014&g=d&ignore=.csv>
[3] pry(main)> Net::HTTP.get(uri)
=> "<!doctype html public \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html><head><title>Yahoo! - 404 Not Found</title><style>\n/* nn4 hide */ \n/*/*/\nbody {font:small/1.2em arial,helvetica,clean,sans-serif;font:x-small;text-align:center;}table {font-size:inherit;font:x-small;}\nhtml>body {font:83%/1.2em arial,helvetica,clean,sans-serif;}input {font-size:100%;vertical-align:middle;}p, form {margin:0;padding:0;}\np {padding-bottom:6px;margin-bottom:10px;}#doc {width:48.5em;margin:0 auto;border:1px solid #fff;text-align:center;}#ygma {text-align:right;margin-bottom:53px}\n#ygma img {float:left;}#ygma div {border-bottom:1px solid #ccc;padding-bottom:8px;margin-left:152px;}#bd {clear:both;text-align:left;width:75%;margin:0 auto 20px;}\nh1 {font-size:135%;text-align:center;margin:0 0 15px;}legend {display:none;}fieldset {border:0 solid #fff;padding:.8em 0 .8em 4.5em;}\nform {position:relative;background:#eee;margin-bottom:15px;border:1px solid #ccc;border-width:1px 0;}\n#s1p {width:15em;margin-right:.1em;}\nform span {position:absolute;left:70%;top:.8em;}form a {font:78%/1.2em arial;display:block;padding-left:.8em;white-space:nowrap;background: url(http://l.yimg.com/a/i/s/bullet.gif) no-repeat left center;} \nform .sep {display:none;}.more {text-align:center;}#ft {padding-top:10px;border-top:1px solid #999;}#ft p {text-align:center;font:78% arial;}\n/* end nn4 hide */\n</style></head>\n<body><div id=\"doc\">\n<div id=\"ygma\"><a href=\"http://us.rd.yahoo.com/404/*http://www.yahoo.com\"><img\nsrc=http://l.yimg.com/a/i/yahoo.gif\nwidth=147 height=31 border=0 alt=\"Yahoo!\"></a><div><a\nhref=\"http://us.rd.yahoo.com/404/*http://www.yahoo.com\">Yahoo!</a>\n - <a href=\"http://us.rd.yahoo.com/404/*http://help.yahoo.com\">Help</a></div></div>\n<div id=\"bd\"><h1>Sorry, the page you requested was not found.</h1>\n<p>Please check the URL for proper spelling and capitalization. If\nyou're having trouble locating a destination on Yahoo!, try visiting the\n<strong><a\nhref=\"http://us.rd.yahoo.com/404/*http://www.yahoo.com\">Yahoo! home\npage</a></strong> or look through a list of <strong><a\nhref=\"http://us.rd.yahoo.com/404/*http://docs.yahoo.com/docs/family/more/\">Yahoo!'s\nonline services</a></strong>. Also, you may find what you're looking for\nif you try searching below.</p>\n<form name=\"s1\" action=\"http://us.rd.yahoo.com/404/*-http://search.yahoo.com/search\"><fieldset>\n<legend><label for=\"s1p\">Search the Web</label></legend>\n<input type=\"text\" size=30 name=\"p\" id=\"s1p\" title=\"enter search terms here\">\n<input type=\"submit\" value=\"Search\">\n<span><a href=\"http://us.rd.yahoo.com/404/*http://search.yahoo.com/search/options?p=\">advanced search</a> <span class=sep>|</span> <a href=\"http://us.rd.yahoo.com/404/*http://buzz.yahoo.com\">most popular</a></span>\n</fieldset></form>\n<p class=\"more\">Please try <strong><a\nhref=\"http://us.rd.yahoo.com/404/*http://help.yahoo.com\">Yahoo!\nHelp Central</a></strong> if you need more assistance.</p>\n</div><div id=\"ft\"><p>Copyright &copy; 2014 Yahoo! Inc.\nAll rights reserved. <a\nhref=\"http://us.rd.yahoo.com/404/*http://privacy.yahoo.com\">Privacy\nPolicy</a> - <a\nhref=\"http://us.rd.yahoo.com/404/*http://docs.yahoo.com/info/terms/\">Terms\nof Service</a></p></div>\n</div></body></html>\n"
查看更多
Juvenile、少年°
3楼-- · 2019-09-17 14:54

Don't try to inject variables into URLs. If they contain characters that need to be encoded per the spec, they won't be by interpolation. Instead, take advantage of the right tools for the job, like Ruby's URI class or the Addressable::URI gem.

See "How to post a URL containting curly braces and colons" for how to do this using well tested wheels.

In your situation, something like this will work:

require 'uri'

code = 'qwer3456*&^%'
start_month = 1
start_day = 1
start_year = 2014
end_month = 12
end_day = 31
end_year = 2015

uri = URI.parse("http://ichart.finance.yahoo.com/table.csv")
uri.query = URI.encode_www_form(
  {
    'g' => 'd',
    'ignore' => '.csv',
    's' => code,
    'a' => start_month,
    'b' => start_day,
    'c' => start_year,
    'd' => end_month,
    'e' => end_day,
    'f' => end_year
  }
)
uri.to_s # => "http://ichart.finance.yahoo.com/table.csv?g=d&ignore=.csv&s=qwer3456*%26%5E%25&a=1&b=1&c=2014&d=12&e=31&f=2015"
查看更多
家丑人穷心不美
4楼-- · 2019-09-17 14:54

Looks like your problem is the ignore=.csv part.

I mean this is probably trying to encode it as a domain extension. Probably you should remove the dot to solve the problem.

查看更多
登录 后发表回答