Как полностью закрыть вкладку с помощью Selenium в Python?

Я пытаюсь выполнить парсинг в Интернете с помощью Selenium, и есть вкладки, которые я открываю для получения некоторой информации, но затем хочу закрыть. Если бы я этого не делал, к тому времени, когда код завершился, у меня было бы открыто много вкладок. Я попытался переключиться на вкладку, которую хочу закрыть, а затем попытался закрыть ее, выполнив следующие действия:

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

Когда я запускаю программу, вкладки остаются открытыми, а там, где обычно находится URL, написано «about: blank». Есть ли способ полностью закрыть эту вкладку, оставив все остальные открытыми? Ниже приведен полный код для справки.

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

Любая помощь приветствуется!

См. также:  Python – создайте текстовую границу с динамическим размером

Росс

Вы хотите закрыть вкладку или браузер?   —  person Ross Leavitt    schedule 19.05.2021

Я просто хочу закрыть вкладку, на которой я нахожусь, когда я ссылаюсь на browser.switch_to.window (browser.window_handles [1]).   —  person Ross Leavitt    schedule 19.05.2021

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 3
  1. Ross Leavitt

    Не думаю, что проблема в driver.close(). Когда я запускаю ваш код, к моменту вызова driver.close() открываются три окна. Я не копался в вашем коде, чтобы точно определить, откуда происходит каждое окно, я предполагаю, что вы в лучшем положении для этого. Но driver.close() просто полностью закрывает вкладку, это ваш код оставляет дополнительную вкладку там.

    Я добавил подобное ведение журнала вокруг вашего driver.close, чтобы показать, что вы получаете дополнительный дескриптор окна в каждом цикле.

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

    Вы можете увидеть из вывода, как накапливаются окна:

    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])
    

    Спасибо, сработало! person Ross Leavitt; 21.05.2021

  2. Ross Leavitt

    Попробуйте следующее:

    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])
    

    Сначала переключитесь на окно, которое хотите закрыть, затем закройте его клавишами Control + w и, наконец, перейдите к начальному окну (вкладке)

    Вкладки все еще там, а URL-адрес по-прежнему пуст. Наверное, это означает, что вкладка технически закрыта, хотя физически все еще открыта … person Ross Leavitt; 19.05.2021

    А какая была вторая вкладка до применения на ней Control + w? person Ross Leavitt; 19.05.2021

  3. Ross Leavitt

    Я бы разместил это в комментарии, но часть кода слишком велика. Я думаю, у вас проблема с отступом. Проверить местонахождение:

    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
    

    Я не обратил особого внимания на некоторые проблемы в вашем коде, поскольку они не являются предметом обсуждения.

    Я думаю, что browser.close оказался в нужном месте, просто не закрыв нужное количество окон. С помощью этого кода после пары циклов открывается только одно окно, когда оно достигает browser.switch_to.window(browser.window_handles[1]), поэтому я получаю browser.switch_to.window(browser.window_handles[1]) IndexError: list index out of range person Ross Leavitt; 19.05.2021

    Ты прав. Я получаю ту же ошибку при втором запуске кода. Но я не всегда получаю эту out of range ошибку. person Ross Leavitt; 19.05.2021

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: