【问题标题】:Selenium doesn't give updated AJAX contentSelenium 不提供更新的 AJAX 内容
【发布时间】:2018-08-27 14:02:09
【问题描述】:

我想从这个网站获取表格内容:“https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2”。什么时候 我检查元素,在 Chrome 浏览器上,我可以在浏览器中显示的 DOMTree 中找到表条目。但是当我运行以下代码时,我得到了一个与https://www.premierleague.com/stats/top/players/red_card 中的表相对应的不同表。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

import time

BASEURL = "https://www.premierleague.com/stats/top/players/"
driver = webdriver.Chrome("/Users/manpreet/Downloads/chromedriver")

driver.get("https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2")

##for i in range(5000):
##    print i
##    time.sleep(1)
try:
    elem = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.XPATH, '//*[@id="mainContent"]/div[2]/div/div[2]/div[1]/div[2]/table'))
    )
finally:
    print('10 secs over')

print(elem.text)

我调用了 WebDriverWait 函数长达 30 秒,但我没有得到正确的表。我注意到,当我使用 WebDriverWait 时,Selenium 打开的浏览器会在整个 30 秒的时间内显示 https://www.premierleague.com/stats/top/players/red_card 中的表格。但是当我不使用WebDriverWait时,驱动程序首先在https://www.premierleague.com/stats/top/players/red_card中显示表格,页面加载几秒钟然后在https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2中显示表格。整个过程只需要大约5-6秒(最多)。我认为当我使用 WebDriverWait 时 Ajax 调用会卡住。这可能是 selenium 无法返回正确表格的原因,因为 Selenium 会抓取显示的内容。

谁能告诉我如何获得正确的表格?

【问题讨论】:

    标签: ajax selenium dom web-crawler


    【解决方案1】:

    你需要更多的等待。

    1. 等到 stat 下拉菜单关闭。您可以等待更改 CSS 样式的“转换”值。请参阅我的回答中的自定义等待 element_transform_changed
    2.等到所有过滤器都显示出来。只需使用 WebDriverWaitEC
    3.睡眠几秒钟等待Javascript执行。使用time.sleep()

    BASEURL = "https://www.premierleague.com/stats/top/players/"
    driver = webdriver.Chrome()
    
    driver.get("https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2")
    
    ##for i in range(5000):
    ##    print i
    ##    time.sleep(1)
    
    class element_transform_changed(object):
        def __init__(self, locator, text):
            self.locator = locator
            self.text = text
    
        def __call__(self, driver):
            wait = WebDriverWait(driver, 20)
            element = wait.until(EC.presence_of_element_located(self.locator))
            newText = element.value_of_css_property("transform")
            if newText is None or len(newText)==0:
                return False
    
            print("OLD: " + self.text + ", NEW: " + newText)
    
            if len(self.text)==0 or (self.text!=newText.strip()):
                return element
            else:
                return False
    
    try:
        WebDriverWait(driver, 40).until(element_transform_changed((By.CSS_SELECTOR, "[data-script='pl_stats'] [class*='topStatsFilterDropdown'] ul"),"matrix(1, 0, 0, 1, 0, 0)"))
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "[data-dropdown-current='FOOTBALL_COMPSEASON']")))
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "[data-dropdown-current='FOOTBALL_CLUB']")))
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "[data-dropdown-current='Nationality']")))
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "[data-dropdown-current='Position']")))
        time.sleep(5)
        elem = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="mainContent"]/div[2]/div/div[2]/div[1]/div[2]/table')))
    except:
        print('ERROR')
    
    print(elem.text)
    time.sleep(10)
    

    【讨论】:

      【解决方案2】:

      我认为 WebDriverWait 不会中断页面​​加载。

      这里要注意的一点是,即使您尝试获取 url https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2(比如第 2 页),应用程序也会首先加载完整列表,如 @987654322 @(比如第 1 页),然后将查询参数传递给过滤器(俱乐部和赛季)。

      现在的问题是,有一个元素可以满足您的元素定位器 EC.presence_of_element_located((By.XPATH, '//[@id="mainContent"]/div[2]/div/div[2]/div[1]/div[2]/表'))* 在第 1 页本身中。 (即在 url https://www.premierleague.com/stats/top/players/red_card 中),所以 selenium 已经获得了它的元素,因此您看到的是 page#1 而不是 page#2 的文本。

      你能做什么:

      ** 你可以在调用 get 方法之后让 Python 休眠一段时间,这样在你尝试定位元素之前,实际页面(page#2)可能会被加载

      ...
      driver.get("https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2")
      time.sleep(3)
      try:
         ...
      

      ** 就在应用程序重定向到第 2 页之前,您可以观察到在页面中设置了过滤器值,并且加载器 div 出现和消失。您可以等到加载程序出现并消失。下面的代码对我有用。

      from selenium import webdriver
      from selenium.webdriver.common.by import By
      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      from selenium.common.exceptions import TimeoutException
      
      import time
      
      # wait for the loading to be complete
      def waitFn(): 
          for x in range(4):
              try:
                  elem = WebDriverWait(driver, delay).until(
                      EC.visibility_of_element_located((By.CSS_SELECTOR, 'div.loader-small'))
                  )
                  elem = WebDriverWait(driver, delay).until(
                      EC.invisibility_of_element_located((By.CSS_SELECTOR, 'div.loader-small'))
                  )
              except TimeoutException:
                  continue
      
      BASEURL = "https://www.premierleague.com/stats/top/players/"
      driver = webdriver.Chrome('/usr/local/bin/chromedriver')
      
      driver.get("https://www.premierleague.com/stats/top/players/red_card?se=42&cl=2")
      delay = 3 # seconds
      
      ##for i in range(5000):
      ##    print i
      # time.sleep(5)
      
      waitFn()
      
      try:
          elem = WebDriverWait(driver, delay).until(
              EC.presence_of_element_located((By.XPATH, '//*[@id="mainContent"]/div[2]/div/div[2]/div[1]/div[2]/table'))
          )
      except TimeoutException:
          print "Loading took too much time!"
      
      finally:
          print(elem.text)
      

      【讨论】:

        猜你喜欢
        • 2018-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        • 2013-07-01
        • 2018-01-29
        • 1970-01-01
        相关资源
        最近更新 更多