【问题标题】:Python pyautogui loop with scrollIntoView becomes stale带有 scrollIntoView 的 Python pyautogui 循环变得陈旧
【发布时间】:2022-01-19 16:43:21
【问题描述】:

我有一个几乎可以运行的 python 脚本,但有一个我无法解决的问题。我的循环正在工作,但仅适用于第一行图像。由于某种原因,网页元素在 3 张图片后变得陈旧。我很肯定有超过 3 个 html 元素与我的查询匹配!我正在使用这个脚本来查看元素driver.execute_script("arguments[0].scrollIntoView(true);", i)。任何想法将不胜感激。

import requests
from bs4 import BeautifulSoup
# from selenium.webdriver.chrome import options
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import time
from selenium.webdriver import ActionChains
from selenium.webdriver.common.action_chains import ActionChains
import pyautogui

# driver_path = '/usr/local/bin/chromedriver'
# driver = webdriver.Chrome(executable_path=driver_path)
options = Options()
driver = webdriver.Firefox(options=options)
driver.get("https://superrare.com/market?market-options=%257B%2522first%2522%3A30%2C%2522orderBy%2522%3A%2522RECENT_NFT_EVENT_BY_TOKEN_CONTRACT_ADDRESS_AND_TOKEN_ID__TIMESTAMP_DESC%2522%2C%2522fileTypes%2522%3A%255B%2522image%2Fjpeg%2522%2C%2522image%2Fpng%2522%255D%2C%2522listPrice%2522%3Afalse%2C%2522isGenesis%2522%3Afalse%2C%2522isSeries%2522%3Afalse%2C%2522neverReceivedOffer%2522%3Afalse%2C%2522reservePrice%2522%3Afalse%2C%2522liveAuctions%2522%3Afalse%2C%2522upcomingAuctions%2522%3Afalse%2C%2522hasSold%2522%3Afalse%2C%2522ownedByCreator%2522%3Afalse%2C%2522openOffers%2522%3Afalse%2C%2522artistsCollected%2522%3Afalse%2C%2522artistsYouFollow%2522%3Afalse%2C%2522artistsThatFollowYou%2522%3Afalse%2C%2522artistsFollowedByFollowed%2522%3Afalse%2C%2522lowerPriceRange%2522%3A0%2C%2522upperPriceRange%2522%3A100000%2C%2522numCreatorSales%2522%3Afalse%2C%2522lowerMintedRange%2522%3Anull%2C%2522upperMintedRange%2522%3Anull%2C%2522startCursor%2522%3A%2522WyJyZWNlbnRfbmZ0X2V2ZW50X2J5X3Rva2VuX2NvbnRyYWN0X2FkZHJlc3NfYW5kX3Rva2VuX2lkX190aW1lc3RhbXBfZGVzYyIsWyIyMDIyLTAxLTE5VDAxOjA3OjAxKzAwOjAwIiwiMHg0MWEzMjJiMjhkMGZmMzU0MDQwZTJjYmM2NzZmMDMyMGQ4Yzg4NTBkIiwxNDQxXV0%3D%2522%2C%2522endCursor%2522%3A%2522WyJyZWNlbnRfbmZ0X2V2ZW50X2J5X3Rva2VuX2NvbnRyYWN0X2FkZHJlc3NfYW5kX3Rva2VuX2lkX190aW1lc3RhbXBfZGVzYyIsWyIyMDIyLTAxLTE4VDEyOjEzOjMzKzAwOjAwIiwiMHhiOTMyYTcwYTU3NjczZDg5ZjRhY2ZmYmU4MzBlOGVkN2Y3NWZiOWUwIiwzMTY4OV1d%2522%2C%2522hasPreviousPage%2522%3Afalse%2C%2522hasNextPage%2522%3Atrue%257D")
actions = ActionChains(driver)

time.sleep(3)

ele=driver.find_element("xpath", '//div[@id="root"]')

total_height = ele.size["height"]
time.sleep(2)  

driver.set_window_size(1920, total_height)
time.sleep(2)



downloadimg = WebDriverWait(driver,50).until(EC.presence_of_all_elements_located((By.XPATH, "//section[contains(@class,'md-media')]")))

for i in downloadimg:
    # bring the webelement into the viewport
    driver.execute_script("arguments[0].scrollIntoView(true);", i)
    downloadimg2 = WebDriverWait(driver,50).until(EC.presence_of_all_elements_located((By.XPATH, "//img[contains(@class,'new-grid-img')]")))
    for img in downloadimg2:
        driver.execute_script("arguments[0].scrollIntoView(true);", img)
        time.sleep(2)
        # determine element's location; the +190 and -100 is to make the mouse show ON the element rather than at it's border
        location = img.location 
        size = img.size 
        x = location['x']+190
        y = location['y']-100   
        # move to the element 
        pyautogui.moveTo((int(x), int(y)), duration=2)
        time.sleep(2)
        # right click
        actions.context_click(img).perform()
        # move to open in new browser tab
        pyautogui.move(0, -25, duration=1)
        time.sleep(1)
        pyautogui.click()
        # move to the new browser tab and click 
        pyautogui.moveTo(480, 50, duration=2)
        pyautogui.click()
        # give time to the img to load
        time.sleep(4)
        # move to the image and click
        pyautogui.moveTo(780, 550, duration=2)
        pyautogui.click()
        # actions.context_click(i).perform()
        # right click and mobe to save img as and then click
        pyautogui.rightClick()
        pyautogui.move(20, 200, duration=2)
        pyautogui.click()
        time.sleep(2)
        # press enter in the dialog box to actually save the img to download folder
        pyautogui.press('enter')
        time.sleep(2)
        # close the tab and go back to the beginning of the loop
        pyautogui.hotkey('command', 'w')
   

【问题讨论】:

  • 刚刚删除了一个没有做任何事情的“while true”行......我想!

标签: python selenium pyautogui staleelementreferenceexception


【解决方案1】:

此特定网站最初并未加载所有图像。
因此,当您滚动到第二行中的图像时,才会加载这些图像。这会导致 web 元素发生变化,因此初始图片列表 downloadimg 变得不再相关,在 Selenium 术语中是 Stale Elements。
为了使您的代码正常工作,您需要在每次滚动后再次获取 downloadimg 列表,如下所示:

downloadimg = WebDriverWait(driver,50).until(EC.presence_of_all_elements_located((By.XPATH, "//img[contains(@class,'new-grid-img')]")))


for i in downloadimg:
    # bring the webelement into the viewport
    driver.execute_script("arguments[0].scrollIntoView(true);", i)
    downloadimg = driver.find_element_by_css_selector('img.new-grid-img')
    time.sleep(2)
    # determine element's location; the +190 and -100 is to make the mouse show ON the element rather than at it's border
    location = i.location 
    size = i.size 
    x = location['x']+190
    y = location['y']-100   
    # move to the element 
    pyautogui.moveTo((int(x), int(y)), duration=2)
    time.sleep(2)
    # right click
    actions.context_click(i).perform()
    # move to open in new browser tab
    pyautogui.move(0, -25, duration=1)
    time.sleep(1)
    pyautogui.click()
    # move to the new browser tab and click 
    pyautogui.moveTo(480, 50, duration=2)
    pyautogui.click()
    # give time to the img to load
    time.sleep(4)
    # move to the image and click
    pyautogui.moveTo(780, 550, duration=2)
    pyautogui.click()
    # actions.context_click(i).perform()
    # right click and mobe to save img as and then click
    pyautogui.rightClick()
    pyautogui.move(20, 200, duration=2)
    pyautogui.click()
    time.sleep(2)
    # press enter in the dialog box to actually save the img to download folder
    pyautogui.press('enter')
    time.sleep(2)
    # close the tab and go back to the beginning of the loop
    pyautogui.hotkey('command', 'w')

你也应该从你的代码中删除多余的driver.quit()

【讨论】:

  • 谢谢@Prophet。我会试试这个。我曾想过类似的事情,但不确定如何在循环中实现。您的行 重新创建了对象,但随后循环的其余部分又引用了“i”。关于将其集成到循环中的任何进一步想法?
  • 是的,这将重新创建/更新 downloadimg 元素列表,而不参考 i,因此您将继续循环。你在这里还需要什么?如果您有任何问题 - 请告诉我
  • 你好@Prophet。我试了又试,但我还没有找到解决方案。您的建议不是集成循环。创建的第二个元素(您建议添加的那个)未在循环中使用。所以我尝试在那个循环中嵌套一个循环来使用你的想法。但它仍然在做同样的事情。
  • 我更改了上面的代码以显示我尝试过的内容。
  • 哈哈!我刚刚更改了我的初始帖子
猜你喜欢
  • 2020-12-29
  • 2015-04-07
  • 2018-12-05
  • 2018-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 1970-01-01
相关资源
最近更新 更多