2017-01-02 72 views
1

我使用Python 3.4,以使該登錄到我的銀行帳戶webscraper,點擊進入每個帳戶中複製的平衡,增加總然後粘貼到谷歌牀單。優化我的蟒蛇銀行webscraper

我得到它的工作,但你可以從代碼中看到,它是重複的,醜陋和長篇大論。

我已經發現了一些問題:

  1. 我相信我應該使用循環功能通過不同的賬戶頁面,以獲得平衡,然後在不同的變量分配值。但我想不出一個辦法完成這件事。

  2. 轉換字符串浮動似乎凌亂,我所要做的就是讓一個字符串即。通過剝離'$'和','$ 1,000.00浮動到一個浮動,是否有更優雅的方式?

    from selenium import webdriver 
    import time 
    import bs4 
    import gspread 
    from oauth2client.service_account import serviceAccountCredentials 
    
    driver = webdriver.Chrome() 
    driver.get(bank url) 
    
    
    inputElement = driver.find_element_by_id("dUsername") 
    inputElement.send_keys('username') 
    pwdElement = driver.find_element_by_id("password") 
    pwdElement.send_keys('password') 
    driver.find_element_by_id('loginBtn').click() 
    time.sleep(3) 
    
    #copies saving account balance 
    driver.find_element_by_link_text('Savings').click() 
    time.sleep(3) 
    html = driver.page_source 
    soup = bs4.BeautifulSoup(html) 
    elems=soup.select('#CurrentBalanceAmount') 
    SavingsAcc = float(elems[0].getText().strip('$').replace(',','')) 
    driver.back() 
    
    #copy cheque balance 
    driver.find_element_by_link_text('cheque').click() 
    time.sleep(3) 
    html = driver.page_source 
    soup = bs4.BeautifulSoup(html) 
    elems=soup.select('#CurrentBalanceAmount') 
    ChequeAcc = float(elems[0].getText().strip('$').replace(',','')) 
    Total = SavingsAcc+ ChequeACC 
    driver.back() 
    

回答

0

試試下面的代碼:

from selenium import webdriver 
import time 
import bs4 
import gspread 
from oauth2client.service_account import serviceAccountCredentials 

driver = webdriver.Chrome() 
driver.get(bank url) 


inputElement = driver.find_element_by_id("dUsername") 
inputElement.send_keys('username') 
pwdElement = driver.find_element_by_id("password") 
pwdElement.send_keys('password') 
driver.find_element_by_id('loginBtn').click() 
time.sleep(3) 

def getBalance(accountType): 
    driver.find_element_by_link_text(accountType).click() 
    time.sleep(3) 
    html = driver.page_source 
    soup = bs4.BeautifulSoup(html) 
    elems=soup.select('#CurrentBalanceAmount') 
    return float(elems[0].getText().strip('$').replace(',','')) 

#copies saving account balance 
SavingsAcc = getBalance('Savings') 
driver.back() 
#copy cheque balance 
ChequeACC = getBalance('cheque')  

Total = SavingsAcc+ ChequeACC 
driver.back() 

製造方法getBalance,在那裏你必須通過帳戶類型,它返回的餘額。

注意:您可以保留driver.back電話getBalance根據您的方便,但在return聲明之前。

有關轉換stringfloat,除了現有的邏輯,我不知道任何其他更好的方法。現在它已經變成了一種方法,我希望現在它不會讓你感到麻煩。有float方法,它轉換字符串浮動,但$,不被接受。更多詳細信息here

注意:如果#CurrentBalanceAmount每次更改不同帳戶類型的值,您可以參數化爲accountType

0

我會用幾個蟒蛇成語清理代碼:

  • 裹在功能
    • 一般來說所有的代碼,把代碼中的功能使得它更容易閱讀和遵守
    • 當你運行一個python腳本(python foo.py)時,python解釋器按順序依次運行它的每一行。遇到函數定義時,它只運行定義行(def bar():),而不運行函數中的代碼。
    • 這篇文章似乎是一個好地方,以獲得有關的更多信息:Understanding Python's Execution Model
  • 使用if __name__ == "__main__":成語,使其可引入模塊
    • 與上述類似子彈,這給你更多的控制權代碼執行的方式和時間,它的可移植性以及它的可重用性。
    • 「可導入的模塊」意味着您可以將您的代碼寫入一個文件,然後將該代碼導入到另一個模塊中。在這裏if __name__ == "__main__"
    • 更多信息:What does if name == 「main」: do?
  • 使用try /終於以確保您的駕駛情況下得到清理
  • 使用明確的等待與網頁互動,這樣你就不需要使用sleep
    • 默認情況下,Selenium會立即嘗試查找並返回事物。如果元素還沒有加載,Selenium會拋出一個異常,因爲它不夠智能,無法等待加載。
    • 顯式等待內置到Selenium中,並允許您的代碼等待元素加載到頁面中。默認情況下,它會每隔半秒檢查一次以查看是否加載了該元素。如果沒有,則只需在另一半秒內再次嘗試。如果有,則返回該元素。如果它沒有加載,則Wait對象將引發TimeoutException。
    • 這裏更多:Explicit and Implicit Waits
    • 在這裏:WAIT IN SELENIUM PYTHON

代碼(未經測試的原因很明顯):

from selenium import webdriver 
from explicit import waiter, ID # This package makes explicit waits easier to use 
           # pip install explicit 
from selenium.webdriver.common.by import By 

# Are any of these needed? 
# import time 
# import bs4 
# import gspread 
# from oauth2client.service_account import serviceAccountCredentials 


def bank_login(driver, username, password): 
    """Log into the bank account""" 
    waiter.find_write(driver, 'dUsername', username, by=ID) 
    waiter.find_write(driver, 'password', password, by=ID, send_enter=True) 


def get_amount(driver, source): 
    """Click the page and scrape the amount""" 
    # Click the page in question 
    waiter.find_element(driver, source, by=By.LINK_TEXT).click() 

    # Why are you using beautiful soup? Because it is faster? 
    # time.sleep(3) 
    # html = driver.page_source 
    # soup = bs4.BeautifulSoup(html) 
    # elems=soup.select('#CurrentBalanceAmount') 
    # SavingsAcc = float(elems[0].getText().strip('$').replace(',','')) 
    # driver.back() 

    # I would do it this way: 
    # When using explicit waits there is no need to explicitly sleep 
    amount_str = waiter.find_element(driver, "CurrentBalanceAmount", by=ID).text 
    # This conversion scheme will handle none $ characters too 
    amount = float("".join([char for char in amount_str if char in ["1234567890."]])) 

    driver.back() 

    return amount 


def main(): 
    driver = webdriver.Chrome() 
    try: 
     driver.get(bank_url) 
     bank_login(driver, 'username', 'password') 
     print(sum([get_amount(driver, source) for source in ['Savings', 'cheque']])) 

    finally: 
     driver.quit() # Use this try/finally idiom to prevent a bunch of dead browsers instances 


if __name__ == "__main__": 
    main() 

全面披露:我保持explicit包。如果您願意,可以用相對較短的等待電話代替上面的waiter電話。如果您正在使用Selenium,那麼值得投入時間來理解和使用顯式等待。

+0

@LeviNoeker這實際上是我從書中學習後的第一個Python代碼,所以我知道的工具是有限的。你能否擴展一點你的觀點? 「if __name__ ==」__main __「是什麼:」do和什麼是可導入的模塊?什麼是明確的等待,它們與睡眠有什麼不同? – fidr

+0

@fidr爲子彈添加了一些附加信息。希望能幫助到你 :-) –