2016-08-17 6 views
8

Yahoo financeが自分のウェブサイトを更新しました。私はlxml/etreeスクリプトを使って、アナリストの推奨事項を抽出しました。しかし、アナリストの提案はそこにありますが、グラフィックとしてのみです。 this pageの例を見ることができます。右列の「推奨動向」というグラフは、強い買い、買い、保有、不足、売りを示すアナリストレポートの数を示しています。ythonからpython lxml etreeアプレット情報

私の推測では、ヤフーは少し時間をかけてページを少し調整しますが、そのようなデータが合理的な方法で抽出可能かどうか疑問に思っています。

  1. つまり、グラフィックスを動作させる方法はありますか?
  2. 成功したとしても、グラフィックからデータを抽出する合理的な方法がありますか?

    url = 'https://finance.yahoo.com/quote/'+code+'/analyst?p='+code 
    tree = etree.HTML(urllib.request.urlopen(url).read()) 
    

    し、HTMLツリー内のデータを見つける:

は、私はこのようなソースを取得するために使用しました。しかし、明らかにそれは不可能です。

+0

メモリから、反応を開始したので、多くのコンテンツが動的に作成されました。どのようにソースを取得していますか? –

+0

私は質問にコードを入れました。コンテンツは動的に作成されているように見えます。とにかくそのようなコンテンツを引き出すことができるのだろうかと思います。 –

+0

はい、私はちょうど見ましたが、それは色付けなどを含めて完全に動的に作成されています。セレンを使って値を取得するのは簡単です。 –

答えて

2

コメントはReactJSに移ったと言うので、lxmlは、HTMLページにデータがないため、もはやポイントにはなりません。今すぐあなたは周りを見回し、彼らがデータを引っ張っているエンドポイントを見つける必要があります。 の場合推奨動向ありがとうございます。

#!/usr/bin/env python3 


import json 
from pprint import pprint 
from urllib.request import urlopen 
from urllib.parse import urlencode 


def parse(): 
    host = 'https://query2.finance.yahoo.com' 
    path = '/v10/finance/quoteSummary/CSX' 
    params = { 
     'formatted' : 'true', 
     'lang'  : 'en-US', 
     'region' : 'US', 
     'modules' : 'recommendationTrend' 
    } 

    response = urlopen('{}{}?{}'.format(host, path, urlencode(params))) 
    data = json.loads(response.read().decode()) 

    pprint(data) 


if __name__ == '__main__': 
    parse() 

出力は次のようになります。

およそたデータはどのよう私が何をしたか

を検索する場所を

{ 
    'quoteSummary': { 
    'error': None, 
    'result': [{ 
     'recommendationTrend': { 
     'maxAge': 86400, 
     'trend': [{ 
      'buy': 0, 
      'hold': 0, 
      'period': '0w', 
      'sell': 0, 
      'strongBuy': 0, 
      'strongSell': 0 
      }, 
      { 
      'buy': 0, 
      'hold': 0, 
      'period': '-1w', 
      'sell': 0, 
      'strongBuy': 0, 
      'strongSell': 0 
      }, 
      { 
      'buy': 5, 
      'hold': 12, 
      'period': '0m', 
      'sell': 2, 
      'strongBuy': 6, 
      'strongSell': 1 
      }, 
      { 
      'buy': 5, 
      'hold': 12, 
      'period': '-1m', 
      'sell': 2, 
      'strongBuy': 7, 
      'strongSell': 1 
      }, 
      { 
      'buy': 6, 
      'hold': 11, 
      'period': '-2m', 
      'sell': 2, 
      'strongBuy': 8, 
      'strongSell': 1 
      }, 
      { 
      'buy': 6, 
      'hold': 11, 
      'period': '-3m', 
      'sell': 2, 
      'strongBuy': 8, 
      'strongSell': 1 
      }] 
     } 
    }] 
    } 
} 

  1. は、ターゲットウィジェット内のいくつかのユニークなトークン(たとえば、チャート値またはトレンド文字列)
  2. オープンを探しますページのソース(HTMLおよびJS用のフォーマッタを使用します(例:this
  3. そこにトークンを探しますeページ3は/* -- Data -- */で始まるセクションです)
  4. スクリプトタグ(またはプログラムの包含物など)を取得するために「.js」を検索します。必要とする。JS)とそこにトークンを探し
  5. Firebugのか、クロム開発者ツールで開くネットワーク]タブとXHRを使用して、ターミナルを好む場合
  6. その後、余分なパラメータを削除し、エンドポイントがどのように反応するか見るために)Postman(またはカールを使用して要求した検査

+0

緑色の技術とフル機能のブラウザとリモコンを比べると;-) – saaj

+0

ええ、私は誰かが直接的なアプローチをしているのではないかと恐れていました。間違いなく恩恵に値する! – alecxe

+0

これは本当にうまくいきます。私は、あなたがパラマウントに入れるべき正しいものをどうやって決めることができたのだろうと思っていましたか?私はそれが何をしているのか曖昧にしか理解していないので、他の情報(目標価格など)にどのようにコードを適応させるのかを理解することは有益だろうと考えました。 –

4

ページはと非常に動的なであり、ブラウザで多くのjavascriptが実行されます。 seleniumに切り替えることについての@ Padraicのアドバイスに従うために、最後に月間傾向の辞書を生成する完全なサンプル作業コードがあります。各バーの値は、バーの高さの比率として計算されます。

from pprint import pprint 

from selenium import webdriver 
from selenium.webdriver.common.by import By 
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.support.wait import WebDriverWait 

driver = webdriver.Chrome() 
driver.maximize_window() 
driver.get("https://finance.yahoo.com/quote/CSX/analysts?p=CSX") 

# wait for the chart to be visible 
wait = WebDriverWait(driver, 10) 
trends = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "section[data-reactid$=trends]"))) 
chart = trends.find_element_by_css_selector("svg.ratings-chart") 

# get labels 
month_names = [month.text for month in chart.find_elements_by_css_selector("g.x-axis g.tick")] 
trend_names = [trend.text for trend in trends.find_elements_by_css_selector("table tr > td:nth-of-type(2)")] 

# construct month-to-trend dictionary 
data = {} 
months = chart.find_elements_by_css_selector("g[transform]:not([class])") 
for month_name, month_data in zip(month_names, months): 
    total = month_data.find_element_by_css_selector("text.total").text 
    data[month_name] = {'total': total} 

    bars = month_data.find_elements_by_css_selector("g.bar rect") 

    # let's calculate the values of bars as proportions of a bar height 
    heights = {trend_name: int(bar.get_attribute("height")) for trend_name, bar in zip(trend_names[::-1], bars)} 
    total_height = sum(heights.values()) 
    for trend_name, bar in zip(trend_names, bars): 
     data[month_name][trend_name] = heights[trend_name] * 100/total_height 

driver.close() 

pprint(data) 

プリント:

{u'Aug': {u'Buy': 19, 
      u'Hold': 45, 
      u'Sell': 3, 
      u'Strong Buy': 22, 
      u'Underperform': 8, 
      'total': u'26'}, 
u'Jul': {u'Buy': 18, 
      u'Hold': 44, 
      u'Sell': 3, 
      u'Strong Buy': 25, 
      u'Underperform': 7, 
      'total': u'27'}, 
u'Jun': {u'Buy': 21, 
      u'Hold': 38, 
      u'Sell': 3, 
      u'Strong Buy': 28, 
      u'Underperform': 7, 
      'total': u'28'}, 
u'May': {u'Buy': 21, 
      u'Hold': 38, 
      u'Sell': 3, 
      u'Strong Buy': 28, 
      u'Underperform': 7, 
      'total': u'28'}} 

total値は、各バーの上部に表示ラベルです。

これは少なくともあなたにとって良いスタートになると思います。私がコードの任意の部分について詳述したり、追加の情報を必要としたいかどうかを教えてください。

関連する問題