簡體   English   中英

如何在 Python 中使用 Selenium 完全關閉選項卡?

[英]How do you fully close a tab by using Selenium in Python?

我正在嘗試用 Selenium 對 web 進行刮擦,並且我打開了一些選項卡以獲取一些信息,但隨后又想關閉它們。 如果我不這樣做,我會在代碼完成運行時打開很多選項卡。 我嘗試切換到要關閉的選項卡,然后嘗試通過執行以下操作將其關閉:

browser.switch_to.window(browser.window_handles[1])
browser.close()

當我運行程序時,盡管選項卡保持打開狀態並且 URL 通常顯示“關於:空白”。 有沒有辦法在保持所有其他標簽打開的同時完全關閉此標簽? 以下是完整代碼供參考。

from selenium import webdriver
import os
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import xlsxwriter
from datetime import datetime
import time
from selenium.common.exceptions import TimeoutException


trade_date_lim = "5/1/2021"


chrome_driver = os.path.abspath('C:/Users/ross/Desktop/chromedriver.exe')
browser = webdriver.Chrome(chrome_driver)


#makes workbook to write to
workbook = xlsxwriter.Workbook('reit_bonds_test.xlsx')
worksheet = workbook.add_worksheet()


stocks = ["PNW", "STWD"]

for stock in stocks:
    browser.get('https://finra-markets.morningstar.com/BondCenter/Default.jsp')
    wait = WebDriverWait(browser, 10)
    #using clicks and send_keys, gets the bond page for a desired stock
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
                                           '#TabContainer > div > div.rtq-tab-wrap > div.rtq-tab-menus-wrap > ul > li:nth-child(3) > a > span'))).click()
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#firscreener-cusip'))).send_keys(stock)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
                                           "#ms-finra-advanced-search-form > div.ms-finra-advanced-search-btn > input:nth-child(2)"))).click()
    try:
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-agreement > input"))).click()
    except TimeoutException:
        pass

    #clicks to sort by earliest date, clicks again to sort by latest maturity
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
    time.sleep(5)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
    time.sleep(5)
    #gathers all bond offerings on first page
    whole_chart = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll"))).text

    #gets number of bonds listed on page so we can iterate through them. Some pages have differing number of bonds listed. Most on page is 20
    parent = browser.find_element_by_xpath('//*[@id="ms-finra-search-results"]/div/div[3]/div[1]/div[1]/div[2]/div[2]/div')
    count_divs = len(parent.find_elements_by_xpath("./div"))

    bnd_off_cnt = 1
    row_num = 0
    while row_num < count_divs and bnd_off_cnt < 3:

        #gets values that I'm looking for
        symbol = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(3)"))).text
        maturity = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(7)"))).text
        moody_rating = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(8)"))).text
        sandp_rating = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(9)"))).text
        stated_bond_yield = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(11)"))).text

        #looks to see if all values are non-empty and if moody rating and sandp rating are not equal to 'WR' and 'NR'
        if symbol.strip() and maturity.strip() and moody_rating.strip() and sandp_rating.strip() and stated_bond_yield.strip() and moody_rating != "WR" and sandp_rating != "NR":
            #bond detail page below
            element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(2) > div > a")))
            element_link = element.get_attribute('href') #gets the link

            #opens window, switches to it and opens the bond detail page
            browser.execute_script("window.open('');")
            time.sleep(3)
            browser.switch_to.window(browser.window_handles[1])
            browser.get(element_link)

            #switch to iframe on second page and clicks it
            wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "ms-bond-detail-iframe")))
            wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#tradeHistory_link"))).click()
            #switches to third page
            browser.switch_to.window(browser.window_handles[-1])
            #sleeps for 3 seconds so we know for sure that we are working on right page
            time.sleep(3)


            # get length of table on trades page and iterate through them trying to find the most recent "Trade" status
            bond_trades = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr")))
            count = len(bond_trades)


            for trade in range(count):

                bond_trade_status = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr:nth-child(" + str(trade + 1) + ") > td:nth-child(4) > div"))).text
                if bond_trade_status == "Trade":
                    bond_last_traded = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr:nth-child(" + str(trade + 1) + ") > td:nth-child(1) > div"))).text
                    if bond_last_traded > trade_date_lim:
                        #prior bond yields occasionally don't match the yield that it was last traded at
                        bond_yield = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr:nth-child(" + str(trade + 1) + ") > td:nth-child(7) > div"))).text
                        print(symbol, maturity, bond_yield)
                        bnd_off_cnt += 1
                        break
                    else:
                        continue
                    #test for if we are within X amount of time from today
                    #continue if we are more than that amount of time
                    #exit if we are within time frame and get 'Yield'
                else:
                    continue
            browser.switch_to.window(browser.window_handles[1])
            browser.close()
            browser.switch_to.window(browser.window_handles[0])
        row_num += 1

任何和所有的幫助表示贊賞!

羅斯

我認為問題不在於driver.close() 當我運行您的代碼時,在您調用driver.close()時打開了三個 windows 。 我還沒有仔細研究你的代碼來弄清楚每個 window 的確切來源,我假設你在一個更好的 position 中可以做到這一點。 但是driver.close()完全關閉選項卡就好了,是您的代碼將額外的選項卡留在那里。

我在您的driver.close周圍添加了這樣的日志記錄,以表明您正在獲得額外的 window 處理每個循環。

print(browser.window_handles)
browser.switch_to.window(browser.window_handles[1])
browser.close()
print(browser.window_handles)

從 output 可以看出 windows 是如何產生的:

PNW5042752 09/15/2050 3.198
['CDwindow-F6F960253D139F2E40A277E65170F5FD', 'CDwindow-5A1FC1679F6C04AA88D09BA7B6568B53', 'CDwindow-DE838D1CED095EF7FEFF8DF3A3242829']
['CDwindow-F6F960253D139F2E40A277E65170F5FD', 'CDwindow-DE838D1CED095EF7FEFF8DF3A3242829']
PNW4989897 05/15/2050 3.217
['CDwindow-F6F960253D139F2E40A277E65170F5FD', 'CDwindow-DE838D1CED095EF7FEFF8DF3A3242829', 'CDwindow-C7B7C24BC2C066C2D42F622ED58A982B', 'CDwindow-9AEBC8F28DFB92B291591730FA45B87B']
['CDwindow-F6F960253D139F2E40A277E65170F5FD', 'CDwindow-C7B7C24BC2C066C2D42F622ED58A982B', 'CDwindow-9AEBC8F28DFB92B291591730FA45B87B']
['CDwindow-F6F960253D139F2E40A277E65170F5FD', 'CDwindow-C7B7C24BC2C066C2D42F622ED58A982B', 'CDwindow-9AEBC8F28DFB92B291591730FA45B87B', 'CDwindow-D3732930FBE9AED7BA22171E4CAE0DCF', 'CDwindow-38527482E16607D629B8DBBA4598AC76']
['CDwindow-F6F960253D139F2E40A277E65170F5FD', 'CDwindow-9AEBC8F28DFB92B291591730FA45B87B', 'CDwindow-D3732930FBE9AED7BA22171E4CAE0DCF', 'CDwindow-38527482E16607D629B8DBBA4598AC76']

解決方案:只需在測試結束時關閉兩個瀏覽器選項卡,而不僅僅是一個。

browser.switch_to.window(browser.window_handles[2])
browser.close()
browser.switch_to.window(browser.window_handles[1])
browser.close()
browser.switch_to.window(browser.window_handles[0])

嘗試以下操作:

browser.switch_to.window(browser.window_handles[1])
browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL, 'w')
browser.switch_to.window(browser.window_handles[0])

首先切換到您想要關閉的 window,然后使用Control + w鍵將其關閉,最后跳轉到初始的 window(選項卡)

我會在評論中發布它,但代碼部分太大了。 我認為你有縮進問題。 檢查位置:

browser.switch_to.window(browser.window_handles[1])
browser.close()
browser.switch_to.window(browser.window_handles[0])

它被移到外循環。 結果是一樣的,打開的標簽要少得多(在我的機器上試過)。

from selenium import webdriver
import os
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import xlsxwriter
from datetime import datetime
import time
from selenium.common.exceptions import TimeoutException


trade_date_lim = "5/1/2021"


chrome_driver = os.path.abspath('C:/Users/ross/Desktop/chromedriver.exe')
browser = webdriver.Chrome(chrome_driver)


#makes workbook to write to
workbook = xlsxwriter.Workbook('reit_bonds_test.xlsx')
worksheet = workbook.add_worksheet()


stocks = ["PNW", "STWD"]

for stock in stocks:
    browser.get('https://finra-markets.morningstar.com/BondCenter/Default.jsp')
    wait = WebDriverWait(browser, 10)
    #using clicks and send_keys, gets the bond page for a desired stock
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
                                           '#TabContainer > div > div.rtq-tab-wrap > div.rtq-tab-menus-wrap > ul > li:nth-child(3) > a > span'))).click()
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#firscreener-cusip'))).send_keys(stock)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,
                                           "#ms-finra-advanced-search-form > div.ms-finra-advanced-search-btn > input:nth-child(2)"))).click()
    try:
        wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-agreement > input"))).click()
    except TimeoutException:
        pass

    #clicks to sort by earliest date, clicks again to sort by latest maturity
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
    time.sleep(5)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-grid-hd > div > div:nth-child(7) > div"))).click()
    time.sleep(5)
    #gathers all bond offerings on first page
    whole_chart = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll"))).text

    #gets number of bonds listed on page so we can iterate through them. Some pages have differing number of bonds listed. Most on page is 20
    parent = browser.find_element_by_xpath('//*[@id="ms-finra-search-results"]/div/div[3]/div[1]/div[1]/div[2]/div[2]/div')
    count_divs = len(parent.find_elements_by_xpath("./div"))

    bnd_off_cnt = 1
    row_num = 0
    while row_num < count_divs and bnd_off_cnt < 3:

        #gets values that I'm looking for
        symbol = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(3)"))).text
        maturity = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(7)"))).text
        moody_rating = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(8)"))).text
        sandp_rating = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(9)"))).text
        stated_bond_yield = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(11)"))).text

        #looks to see if all values are non-empty and if moody rating and sandp rating are not equal to 'WR' and 'NR'
        if symbol.strip() and maturity.strip() and moody_rating.strip() and sandp_rating.strip() and stated_bond_yield.strip() and moody_rating != "WR" and sandp_rating != "NR":
            #bond detail page below
            element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-finra-search-results > div > div.qs-resultData > div.qs-resultData-body > div.rtq-grid.rtq-grid-auto-h > div.rtq-scrollpanel > div.rtq-grid-scroll > div > div:nth-child(" + str(row_num + 1) + ") > div:nth-child(2) > div > a")))
            element_link = element.get_attribute('href') #gets the link

            #opens window, switches to it and opens the bond detail page
            browser.execute_script("window.open('');")
            time.sleep(3)
            browser.switch_to.window(browser.window_handles[1])
            browser.get(element_link)

            #switch to iframe on second page and clicks it
            wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "ms-bond-detail-iframe")))
            wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#tradeHistory_link"))).click()
            #switches to third page
            browser.switch_to.window(browser.window_handles[-1])
            #sleeps for 3 seconds so we know for sure that we are working on right page
            time.sleep(3)


            # get length of table on trades page and iterate through them trying to find the most recent "Trade" status
            bond_trades = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr")))
            count = len(bond_trades)


            for trade in range(count):

                bond_trade_status = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr:nth-child(" + str(trade + 1) + ") > td:nth-child(4) > div"))).text
                if bond_trade_status == "Trade":
                    bond_last_traded = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr:nth-child(" + str(trade + 1) + ") > td:nth-child(1) > div"))).text
                    if bond_last_traded > trade_date_lim:
                        #prior bond yields occasionally don't match the yield that it was last traded at
                        bond_yield = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ms-glossary > div > table > tbody > tr:nth-child(" + str(trade + 1) + ") > td:nth-child(7) > div"))).text
                        print(symbol, maturity, bond_yield)
                        bnd_off_cnt += 1
                        break
                    else:
                        continue
                    #test for if we are within X amount of time from today
                    #continue if we are more than that amount of time
                    #exit if we are within time frame and get 'Yield'
                else:
                    continue
        browser.switch_to.window(browser.window_handles[1])
        browser.close()
        browser.switch_to.window(browser.window_handles[0])
        row_num += 1

我沒有過多關注您代碼中的一些問題,因為它們不在問題中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM