373351 (4) [Avatar] Offline
#1
I am getting this error:


result['ah_price'] = quote.find('span',attrs={'id':'yfs_l86_'+tick}).string
AttributeError: 'NoneType' object has no attribute 'string'

I've tried:

1) Updating the script with the new IDs
2) When I print html in the interpreter, the html is printed to the screen
3) quote does not print to the screen after I run the script, but if I run the function line by line in the interpreter I get the rt_quote_summary section:

<div class="yfi_rt_quote_summary" id="yfi_rt_quote_summary"><div class="hd"><div class="title"><h2>Alphabet Inc. (GOOG)</h2> <span class="rtq_exch"><span class="rtq_dash">-</span>NasdaqGS </span><span class="wl_sign"></span></div></div><div class="yfi_rt_quote_summary_rt_top sigfig_promo_1"><div> <span class="time_rtq_ticker"><span id="yfs_l84_goog">709.90</span></span> <span class="up_g time_rtq_content"><span id="yfs_c63_goog"><img alt="Up" border="0" class="pos_arrow" height="14" src="http://l.yimg.com/os/mit/media/m/base/images/transparent-1093278.png" style="margin-right:-2px;" width="10"/> 1.41</span><span id="yfs_p43_goog">(0.20%)</span> </span><span class="time_rtq"> <span id="yfs_t53_goog"><span id="yfs_t53_goog">10:13AM EDT</span></span></span> - Nasdaq Real Time Price</div><div></div></div><div id="yfi_toolbox_mini_rtq"><span class="fb-like-button"></span><script type="text/javascript">
ll_js.push({
'script':function(){
YUI().use('node', function (Y) {
var iframe = Y.Node.create('<iframe src="http://www.facebook.com/plugins/like.php?href=http://finance.yahoo.com%2Fq%3Fs%3DGOOG&layout=button_count&show_faces=false&action=like&font=arial&colorscheme=light&height=21&width=100&locale=en_US" scrolling="no" frameborder="0" allowTransparency="true" style="height:21px; width:95px;"></iframe>');
Y.one(".fb-like-button").append(iframe);
});
}
});
</script></div></div>


362000 (2) [Avatar] Offline
#2
I'm not intimately familiar with Yahoo's schema, but either it changes daily, or it's changed significantly since this book was published (the more likely explanation).

Here's the code that ended up working for me:

def parse_stock_html(html, ticker_name):
quote = find_quote_section(html)
result = {}
tick = ticker_name.lower()

# <h2>Google Inc.</h2>
result['stock_name'] = quote.find('h2').contents[0]

### After hours value
# <span id="yfs_l91_goog">329.94</span>
result['ah_price'] = quote.find('span', attrs = {'id' : 'yfs_l86_'+tick}).string

# <span id="yfs_z08_goog">
# <span class = "yfi-price-change-down">0.22</span>
result['ah_change'] = quote.find(attrs = {'id': 'yfs_c85_' + tick}).string

### Current values
# <span id="yfs_l10_goog">330.16</span>
result['last_trade'] = quote.find('span', attrs = {'id' : 'yfs_l84_' + tick}).string

# <span id="yfs_c10_goog" class="yfi_quote_price">
# <span class="yfi-price-change-down">1.06</span>
def is_price_change(value):
return (value is not None and value.strip().lower().startswith('yfi-price-change'))

result['change'] = quote.find(attrs={'id': 'yfs_c63_' + tick}).string

return result
362000 (2) [Avatar] Offline
#3
For what it's worth - next day, the code is no longer valid. The identifiers used during active trading differ from that used during after-hours.

The function
is_price_change(value)

does not work as Yahoo has changed how they tag price changes (yfi-price-change-red or yfi-price-change-green).

Furthermore, I don't even understand how that function was supposed to work in context being called in
.find(attrs={'class': is_price_change})


What is value supposed to represent? And let's say the function returns TRUE. How does
.find(attrs={'class': TRUE})

make any sense?

Anyhow, I ended up hard-coding the results so I could move on with the rest of the chapter.