2017-12-21 28 views
0

다음 코드를 사용하려고합니다. 하지만 첫 번째 선택한 날짜와 같은 데이터의 5 배가됩니다.MechanicalSoup에서 선택한 데이터를 catch하지 않습니다.

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

. 반면 실제 웹 브라우저에서 거래 날짜를 손으로 설정하면 #tradeDate=12/15/2017이 URL에 추가됩니다.

웹 브라우저에서 URL을 가져 와서 MechanicalSoup로 열어도 JavaScript가 처리되지 않기 때문에 올바르게 표시되지 않습니다. 당신은 다음과 같은 방법으로 루프에 대한 당신의 마지막을 수정하여이를 볼 수 있습니다

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

Daniel 많은 설명에 감사드립니다. 당신이 말했듯이 나는 Selenium으로 시도했다. 잘 작동합니다! – alexcape