簡體   English   中英

如何遍歷每10秒刷新一次的Web元素列表?

[英]How to iterate trough a list of web elements that is refreshing every 10 sec?

我正在嘗試遍歷每10秒刷新一次的列表。

這是我嘗試過的:

driver.get("https://www.winmasters.ro/ro/live-betting/")

events = driver.find_elements_by_css_selector('.event-wrapper.v1.event-live.odds-hidden.event-sport-1')
for i in range(len(events)):
    try:
        event = events[i]
        name = event.find_element_by_css_selector('.event-details-team-name.event-details-team-a')# the error occurs here
    except: # NoSuchElementException or StaleElementReferenceException 
        time.sleep(3) # i have tried up to 20 sec
        event = events[i]        
        name = event.find_element_by_css_selecto('.event-details-team-name.event-details-team-a')

這沒有用,所以我嘗試了另一個

    except: # second try that also did not work
        element = WebDriverWait(driver, 20).until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.event-details-team-name.event-details-team-a'))
        )
        name = event.find_element_by_css_selecto('.event-details-team-name.event-details-team-a')

現在,我分配了一些我永遠不會使用的name例如:

try:
    event = events[i]
    name = event.find_element_by_css_selector('.event-details-team-name.event-details-team-a')
except:
    name = "blablabla"

使用此代碼,當頁面刷新時,我得到大約“ blablabla”的7或8,直到它再次從網頁中找到我的選擇器

一個主要問題是您要先獲取所有元素,然后遍歷該列表。 由於頁面本身經常更新,因此您已經獲取的元素已經“過時”,這意味着它們不再與當前的DOM對象相關聯。 當您嘗試使用那些過時的元素時,Selenium會引發StaleElementReferenceExceptions,因為它無法對那些過時的對象執行任何操作。

解決此問題的一種方法是僅在需要時才獲取和使用元素,而不是預先獲取所有元素。 我個人認為最干凈的方法是使用CSS :nth-child()方法:

from selenium import webdriver


def main():
    base_css = '.event-wrapper.v1.event-live.odds-hidden.event-sport-1'
    driver = webdriver.Chrome()
    try:
        driver.get("https://www.winmasters.ro/ro/live-betting/")

        # Get a list of all elements
        events = driver.find_elements_by_css_selector(base_css)
        print("Found {} events".format(len(events)))

        # Iterate through the list, keeping track of the index
        # note that nth-child referencing begins at index 1, not 0
        for index, _ in enumerate(events, 1):
            name = driver.find_element_by_css_selector("{}:nth-child({}) {}".format(
                base_css,
                index,
                '.event-details-team-name.event-details-team-a'
            ))
            print(name.text)
    finally:
        driver.quit()


if __name__ == "__main__":
    main()

如果運行上面的腳本,則會得到以下輸出:

$ python script.py
Found 2 events
Hapoel Haifa
FC Ashdod

現在,由於基礎網頁確實確實更新了很多,因此您仍然有很多機會遇到SERE錯誤。 為了克服這個問題,您可以使用重試裝飾器( pip install retry來獲取軟件包)來處理SERE並重新獲取元素:

import retry
from selenium import webdriver
from selenium.common.exceptions import StaleElementReferenceException


@retry.retry(StaleElementReferenceException, tries=3)
def get_name(driver, selector):
    elem = driver.find_element_by_css_selector(selector)
    return elem.text


def main():
    base_css = '.event-wrapper.v1.event-live.odds-hidden.event-sport-1'
    driver = webdriver.Chrome()
    try:
        driver.get("https://www.winmasters.ro/ro/live-betting/")

        events = driver.find_elements_by_css_selector(base_css)
        print("Found {} events".format(len(events)))
        for index, _ in enumerate(events, 1):
            name = get_name(
                driver,
                "{}:nth-child({}) {}".format(
                    base_css,
                    index,
                    '.event-details-team-name.event-details-team-a'
                )
            )
            print(name)
    finally:
        driver.quit()


if __name__ == "__main__":
    main()

現在,盡管有上述示例,我認為您的CSS選擇器仍然存在問題,這是NoSuchElement異常的主要原因。 如果沒有更好地描述您實際上要使用此腳本完成的工作,我將無濟於事。

您可以使用JavaScript獲取所有必需的數據。
下面的代碼將為您提供帶有所有詳細信息的事件map列表,並且立即出現NoSuchElementExceptionStaleElementReferenceException錯誤:
me_id :唯一標識符
href :href包含詳細信息,您可以用來獲取詳細信息
team_a :第一隊的名字
team_a_score :第一隊得分
team_b :第二支隊伍的名字
team_b_score :第二隊得分
event_status :事件狀態
event_clock :事件的時間

def events = driver.execute_script('return [...document.querySelectorAll(\'[data-uat="live-betting-overview-leagues"] .events-for-league .event-live\')].map(e=>{return {me_id:e.getAttribute("me_id"), href:e.querySelector("a.event-details-live").href, team_a:e.querySelector(".event-details-team-a").textContent, team_a_score:e.querySelector(".event-details-score-1").textContent, team_b:e.querySelector(".event-details-team-b").textContent, team_b_score:e.querySelector(".event-details-score-2").textContent, event_status:e.querySelector(\'[data-uat="event-status"]\').textContent, event_clock:e.querySelector(\'[data-uat="event-clock"]\').textContent}})')
for event in events:
    print(event.get('me_id'))
    print(event.get('href')) #using href you can open event details using: driver.get(event.get('href'))
    print(event.get('team_a'))
    print(event.get('team_a_score'))
    print(event.get('team_b'))
    print(event.get('team_b_score'))
    print(event.get('event_status'))
    print(event.get('event_clock'))

暫無
暫無

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

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