2017-12-21 34 views
0

次のコードを使用しようとしています。しかし、私は最初に選択された日付の5倍の同じデータを取得します。MechanicalSoupが選択したデータをキャッチしない

import re 
import datetime 
import mechanicalsoup 

def get_EminiTable(soup): 
    allValues = [] 
    colnames = soup.find('thead').get_text() 
    allValues.append([i for i in colnames.split('\n') if len(i) > 1]) 
    lnr = 0 
    for line in soup.tbody.find_all('tr'): 
     allValues.append([i for i in line.get_text().split('\n') if len(i) > 0]) 
     if 'UNCH' in allValues: 
      allValues.pop() 
     if lnr > 1: break 
     lnr += 1 
    return allValues 

def get_settldays(soup): 
    settlDays = soup.find('select', id="cmeTradeDate").get 
    settlDays = re.findall('\d\d/\d\d/\d\d\d\d',str(settlDays)) 
    return [datetime.datetime.strptime(adat, '%m/%d/%Y') for adat in settlDays] 


url = "http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html" 
browser = mechanicalsoup.StatefulBrowser() 
if str(browser.open(url)) != '<Response [200]>': 
    print('Error') 
    quit() 
soup = browser.get_current_page() 
settlDays = get_settldays(soup) 
for adate in settlDays: 
    form = browser.select_form('form[id="quotesoptionsform1"]') 
    form.set("tradeDate",adate.__format__('%m/%d/%Y')) 
    browser.submit_selected() 
    soup = browser.get_current_page() 
    tabvals = get_EminiTable(soup) 
    print(adate) 
    for each in tabvals: 
     print(each) 
browser.session.close() 
browser.close() 

さまざまなテーブルの正しい日付を得るための考え方、またはmechanicalsoupのバグです。

答えて

0

私は、このフォームがHTTPではなくJavaScriptによって処理されるため、HTTPリクエスト(これはMechanicalSoupの動作方法)でフォームを送信しても実際には何もしないためです。

MechanicalSoupは、次の構文でリクエストのURLを作成します。あなたはこのリンクをクリックすると、あなたは、クエリ文字列&action=Submit&tradeDate=12%2F15%2F2017が無視されていることがわかります

http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html?action=Submit&tradeDate=12%2F15%2F2017

。実際のWebブラウザで取引日付を手動で設定すると、URLに#tradeDate=12/15/2017が追加されていることがわかります。

ウェブブラウザからそのURLを取得してMechanicalSoupで開くとしても、JavaScriptが処理されないため正しく表示されません。あなたは次のようにforループ最後を変更することで、これを見ることができます:

for adate in settlDays: 
    # Open the URL for each date directly 
    date = adate.__format__('%m/%d/%Y') 
    resp = browser.open(url + "#tradeDate={}".format(date)) 

    # Make sure we constructed the URL correctly 
    print(resp.url) 

    # Print the date that is being displayed 
    soup = browser.get_current_page() 
    print(soup.find('select', id='cmeTradeDate').find('option', attrs={'selected': 'selected'}).text) 

出力は(構文の強調表示を無視して...)のようになります。誰かが代わりを知っている場合を除き

http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html#tradeDate=12/21/2017 
Thursday, 21 Dec 2017 (Prelim) 
http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html#tradeDate=12/20/2017 
Thursday, 21 Dec 2017 (Prelim) 
http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html#tradeDate=12/19/2017 
Thursday, 21 Dec 2017 (Prelim) 
http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html#tradeDate=12/18/2017 
Thursday, 21 Dec 2017 (Prelim) 
http://www.cmegroup.com/trading/equity-index/us-index/e-mini-sandp500_quotes_settlements_futures.html#tradeDate=12/15/2017 
Thursday, 21 Dec 2017 (Prelim) 

HTTPでこのページを処理するには、実際のブラウザをシミュレートするSeleniumなど、JavaScriptとやり取りできるツールを使用するのが最善の方法だと思います。

+0

ダニエルあなたの説明に感謝します。あなたが言ったように、私はセレンとそれを試しました。それはうまく動作します! – alexcape

関連する問題