Discuss / JavaScript / YAHOO天气API解析错误原因分析

YAHOO天气API解析错误原因分析

Topic source

结论:是我们的姿势错了.

YAHOO没有错.

yahoo作为一个老牌过气大厂,还不至于连个json都生成不好.

错的是我们获取json字符串的姿势.

我猜大家都是用浏览器直接打开了yahaoo天气api的url,然后将显示在页面上的内容拿回来用JSON.parse解析,发现各种报错的.

原理如下:

1.yahoo生成json字符串的时候\n已经转化为了\\n, 2.而我们用浏览器去查看这段字符串,浏览器把\\n(渲|污)染成\n给我们看. 3.我们不知有诈,直接将浏览器这个小婊子显示的\n复制回了家 4.然后JSON.parse的时候就炸了

为了明我的判断正确,下面用python来获取获取没有被污染的json字符串.

In [69]: from urllib import request

In [70]: resp=request.urlopen('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=json')

In [71]: resp_text=resp.read() #拿到字符串

In [72]: resp_text #查看一下
Out[72]: b'{"query":{"count":1,"created":"2016-10-16T05:32:32Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"F"},"title":"Yahoo!
 Weather - Beijing, Beijing, CN","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2151330/","description":"Yahoo! Weather f
or Beijing, Beijing, CN","language":"en-us","lastBuildDate":"Sun, 16 Oct 2016 01:32 PM CST","ttl":"60","location":{"city":"Beijing","country":"China","region":" Beijing"},"wind":{"chill":"66
","direction":"225","speed":"7"},"atmosphere":{"humidity":"65","pressure":"1013.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"6:27 am","sunset":"5:32 pm"},"image":{"title":"Ya
hoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Beijing, Beiji
ng, CN at 12:00 PM CST","lat":"39.90601","long":"116.387909","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2151330/","pu
bDate":"Sun, 16 Oct 2016 12:00 PM CST","condition":{"code":"28","date":"Sun, 16 Oct 2016 12:00 PM CST","temp":"65","text":"Mostly Cloudy"},"forecast":[{"code":"28","date":"16 Oct 2016","day"
:"Sun","high":"68","low":"53","text":"Mostly Cloudy"},{"code":"32","date":"17 Oct 2016","day":"Mon","high":"68","low":"51","text":"Sunny"},{"code":"32","date":"18 Oct 2016","day":"Tue","high
":"68","low":"48","text":"Sunny"},{"code":"34","date":"19 Oct 2016","day":"Wed","high":"72","low":"51","text":"Mostly Sunny"},{"code":"28","date":"20 Oct 2016","day":"Thu","high":"64","low":
"56","text":"Mostly Cloudy"},{"code":"26","date":"21 Oct 2016","day":"Fri","high":"61","low":"56","text":"Cloudy"},{"code":"28","date":"22 Oct 2016","day":"Sat","high":"58","low":"51","text"
:"Mostly Cloudy"},{"code":"30","date":"23 Oct 2016","day":"Sun","high":"56","low":"43","text":"Partly Cloudy"},{"code":"28","date":"24 Oct 2016","day":"Mon","high":"57","low":"42","text":"Mo
stly Cloudy"},{"code":"30","date":"25 Oct 2016","day":"Tue","high":"59","low":"47","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\\"http://l.yimg.com/a/i/us/we/52/28.gif\\"/>\\n<
BR />\\n<b>Current Conditions:</b>\\n<BR />Mostly Cloudy\\n<BR />\\n<BR />\\n<b>Forecast:</b>\\n<BR /> Sun - Mostly Cloudy. High: 68Low: 53\\n<BR /> Mon - Sunny. High: 68Low: 51\\n<BR /> Tue
 - Sunny. High: 68Low: 48\\n<BR /> Wed - Mostly Sunny. High: 72Low: 51\\n<BR /> Thu - Mostly Cloudy. High: 64Low: 56\\n<BR />\\n<BR />\\n<a href=\\"http://us.rd.yahoo.com/dailynews/rss/weath
er/Country__Country/*https://weather.yahoo.com/country/state/city-2151330/\\">Full Forecast at Yahoo! Weather</a>\\n<BR />\\n<BR />\\n(provided by <a href=\\"http://www.weather.com\\" >The W
eather Channel</a>)\\n<BR />\\n]]>","guid":{"isPermaLink":"false"}}}}}}'
# 上方原生态的的\\n多么的醒目
In [73]: import json

In [74]: jsonobj=json.loads(resp_text.decode('utf-8'))
#parse一下,完全没有炸

In [75]: jsonobj
Out[75]:
{'query': {'count': 1,
  'created': '2016-10-16T05:32:32Z',
  'lang': 'en-US',
  'results': {'channel': {'astronomy': {'sunrise': '6:27 am',
     'sunset': '5:32 pm'},
    'atmosphere': {'humidity': '65',
     'pressure': '1013.0',
     'rising': '0',
     'visibility': '16.1'},
    'description': 'Yahoo! Weather for Beijing, Beijing, CN',
    'image': {'height': '18',
     'link': 'http://weather.yahoo.com',
     'title': 'Yahoo! Weather',
     'url': 'http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif',

证明完毕.

这里有一份福利给大家. Out[76] 就是我们想要的yahoo生成未被污染过的json字符串

In [76]: resp_text.decode('utf-8')
Out[76]: '{"query":{"count":1,"created":"2016-10-16T05:32:32Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"F"},"title":"Yahoo! Weather - Beijing, Beijing, CN","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2151330/","description":"Yahoo! Weather for Beijing, Beijing, CN","language":"en-us","lastBuildDate":"Sun, 16 Oct 2016 01:32 PM CST","ttl":"60","location":{"city":"Beijing","country":"China","region":" Beijing"},"wind":{"chill":"66","direction":"225","speed":"7"},"atmosphere":{"humidity":"65","pressure":"1013.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"6:27 am","sunset":"5:32 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Beijing, Beijing, CN at 12:00 PM CST","lat":"39.90601","long":"116.387909","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2151330/","pubDate":"Sun, 16 Oct 2016 12:00 PM CST","condition":{"code":"28","date":"Sun, 16 Oct 2016 12:00 PM CST","temp":"65","text":"Mostly Cloudy"},"forecast":[{"code":"28","date":"16 Oct 2016","day":"Sun","high":"68","low":"53","text":"Mostly Cloudy"},{"code":"32","date":"17 Oct 2016","day":"Mon","high":"68","low":"51","text":"Sunny"},{"code":"32","date":"18 Oct 2016","day":"Tue","high":"68","low":"48","text":"Sunny"},{"code":"34","date":"19 Oct 2016","day":"Wed","high":"72","low":"51","text":"Mostly Sunny"},{"code":"28","date":"20 Oct 2016","day":"Thu","high":"64","low":"56","text":"Mostly Cloudy"},{"code":"26","date":"21 Oct 2016","day":"Fri","high":"61","low":"56","text":"Cloudy"},{"code":"28","date":"22 Oct 2016","day":"Sat","high":"58","low":"51","text":"Mostly Cloudy"},{"code":"30","date":"23 Oct 2016","day":"Sun","high":"56","low":"43","text":"Partly Cloudy"},{"code":"28","date":"24 Oct 2016","day":"Mon","high":"57","low":"42","text":"Mostly Cloudy"},{"code":"30","date":"25 Oct 2016","day":"Tue","high":"59","low":"47","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\\"http://l.yimg.com/a/i/us/we/52/28.gif\\"/>\\n<BR />\\n<b>Current Conditions:</b>\\n<BR />Mostly Cloudy\\n<BR />\\n<BR />\\n<b>Forecast:</b>\\n<BR /> Sun - Mostly Cloudy. High: 68Low: 53\\n<BR /> Mon - Sunny. High: 68Low: 51\\n<BR /> Tue - Sunny. High: 68Low: 48\\n<BR /> Wed - Mostly Sunny. High: 72Low: 51\\n<BR /> Thu - Mostly Cloudy. High: 64Low: 56\\n<BR />\\n<BR />\\n<a href=\\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2151330/\\">Full Forecast at Yahoo! Weather</a>\\n<BR />\\n<BR />\\n(provided by <a href=\\"http://www.weather.com\\" >The Weather Channel</a>)\\n<BR />\\n]]>","guid":{"isPermaLink":"false"}}}}}}'

复制out[76] 两个单引号之间的部分 在浏览器控制台下输入> JSON.parse(粘贴到括号里边); 按下enter 看结果.

祝你成功.

复制out[76] 两个单引号之间的部分,包含两端的单引号.

不对不对,复制out[76] 两个单引号之间的部分,不包含两端的单引号. 原本用单引号的地方应该用新学的呻吟符下方的反引号代替. 这是呻吟符~~~~~~~~~~~~~ 反引号在这里会被转义,写在下面:

`

筱潇梦语

#4 Created at ... [Delete] [Delete and Lock User]

没看懂,这个怎么用?

亲测有效,谢谢了

草O的生活

#6 Created at ... [Delete] [Delete and Lock User]

老哥稳

赤_子

#7 Created at ... [Delete] [Delete and Lock User]

var json = document.getElementsByTagName("pre")[0].childNodes[0].nodeValue; 我打开页面之后就拿到了。。。貌似没有那么复杂?

赤_子

#8 Created at ... [Delete] [Delete and Lock User]

JSON.stringify(JSON.parse(json), null, " "); 我拿到的本身就是JSON格式,但是很难阅读,就先转换成了对象,然后再将其序列化,便于阅读。

成功了,老哥,厉害啊


  • 1

Reply