我正在编写一个脚本,该脚本在instagram照片上设置了喜欢,但在喜欢后(一次14次,一次50次,一次64次),shell给我这个错误:
in <module> ui.WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".dCJp8.afkep.coreSpriteHeartOpen._0mzm-"))).click() File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/selenium/webdriver/support/wait.py", line 80, in until raise TimeoutException(message, screen, stacktrace) TimeoutException: Message:
我知道问题应该出在webdriver等待中,但是我不知道如何改善我的脚本。
这是我的脚本:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome(executable_path = '/usr/local/bin/chromedriver')
driver.implicitly_wait(30)
driver.get("https://www.instagram.com/accounts/login/?source=auth_switcher")
#log in
time.sleep(1)
usm = driver.find_element_by_name('username').send_keys("givcomomvrvglino")
pwd = driver.find_element_by_name('password').send_keys("x")
btnLog = driver.find_element_by_tag_name('form').submit()
#disattiva le notifiche
ui.WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,".aOOlW.HoLwm"))).click()
tag = "likeforfollow"
url_to_search = "https://www.instagram.com/explore/tags/" + tag + "/"
driver.get(url_to_search)
contatore = 0
for i in range(500):
if i == 0:
ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".v1Nh3.kIKUG._bz0w"))).click()
ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".dCJp8.afkep.coreSpriteHeartOpen._0mzm-"))).click()
ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".HBoOv.coreSpriteRightPaginationArrow"))).click()
else:
ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".dCJp8.afkep.coreSpriteHeartOpen._0mzm-"))).click()
ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".HBoOv.coreSpriteRightPaginationArrow"))).click()
contatore = contatore + 1
print(contatore)
time.sleep(3)
答案 0 :(得分:0)
首先关于异常。
TimeoutException当命令未在足够的时间内完成时抛出。
WebDriverWait默认情况下每500毫秒调用ExpectedCondition,直到成功返回。对于ExpectedCondition类型,成功返回是Boolean返回true,对于所有其他ExpectedCondition类型,返回值都是非null。
您正在使用Explicit Waits条件。这将等待您指定的条件,然后再继续执行代码。如果驱动程序在指定的时间内找不到该元素,则将抛出TimeoutException。您将需要增加等待时间,以解决在指定的指定时间范围内未加载的元素。
关于如何改进代码,我建议使用Implicit Waits,因为一旦调用此函数,它将在webdriver对象的生命周期内进行设置。
有关设置方法的示例
driver.implicitly_wait(30) # 30 seconds to wait. This tells the Webdriver to poll the DOM for a certain amount of time.
driver.get("http://")
my_element = driver.findElement(By.cssSelector(".v1Nh3.kIKUG._bz0w"))).click()
这一次到期后,将引发异常。隐式等待优于显式等待的好处是您无需重复添加诸如WebDriverWait(driver, 20).until(EC.element_to_be_clickable
之类的代码。现在,隐式等待的缺点在于,如果需要,则不允许预期的条件。
如果确实需要使用“显式等待”,则可以在try块中创建一次Webdriver实例,也可以通过设置脚本/方法来完成。我看不到完整的脚本,但是如果您没有在脚本末尾添加quit(),则需要这样做。退出将关闭浏览器并关闭已启动的Driver可执行文件。 Quit()方法可以在finally块中或在tearDown方法中调用。
更新: 其他几点。 您不建议同时使用隐式和显式等待,请查看有关此问题do not mix implicit and explicit waits的更多详细信息。我更新了您的代码,使其仅使用显式代码,但可以轻松对其进行更改,因此我建议您使用。 我还将等待时间增加到30秒,查看第10行
OR
wait = ui.WebDriverWait(驱动程序,30)#等待30秒
我添加了评论,请阅读。
示例
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
try:
driver = webdriver.Chrome(executable_path = '/usr/local/bin/chromedriver')
#=======================================================================
# Create a single instance for WebDriverWait.
# Defines how long to wait.
#=======================================================================
wait = ui.WebDriverWait(driver, 30) # wait for 30 seconds
driver.get("https://www.instagram.com/accounts/login/?source=auth_switcher")
#log in
time.sleep(1)
usm = driver.find_element_by_name('username').send_keys("givcomomvrvglino")
pwd = driver.find_element_by_name('password').send_keys("x")
btnLog = driver.find_element_by_tag_name('form').submit()
#disattiva le notifiche
#=======================================================================
# A successful return is for ExpectedCondition type is Boolean return true or not
# null return value for all other ExpectedCondition types.
#=======================================================================
element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,".aOOlW.HoLwm")))
element.click() # click on element
tag = "likeforfollow"
url_to_search = "https://www.instagram.com/explore/tags/" + tag + "/"
driver.get(url_to_search)
contatore = 0
for i in range(500):
if i == 0:
#=======================================================================
# A successful return is for ExpectedCondition type is Boolean return true or not
# null return value for all other ExpectedCondition types.
#=======================================================================
element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".v1Nh3.kIKUG._bz0w")))
element.click() # click on element
element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".dCJp8.afkep.coreSpriteHeartOpen._0mzm-")))
element.click() # click on element
element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".HBoOv.coreSpriteRightPaginationArrow")))
element.click() # click on element
else:
element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".dCJp8.afkep.coreSpriteHeartOpen._0mzm-")))
element.click() # click on element
element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".HBoOv.coreSpriteRightPaginationArrow")))
element.click() # click on element
contatore = contatore + 1
print(contatore)
time.sleep(3)
finally:
driver.close() # close driver executable and chrome browser.
最后,我看到您正在使用CSS选择器来查找所有元素。我认为CSS选择器和ID是一个不错的选择。现在,关于应始终尝试使用哪些选择器,网上有很多争论,因此您可以简单地进行搜索,但是如果您有兴趣,那是我发现对选择哪种选择器有所帮助的特定讨论。请参考堆栈溢出答案。 selectors
答案 1 :(得分:0)
正如您提到的, shell有时会在点赞之后(一次14次,一次50次,一次64次)给出此错误,因此实际上似乎没有确定/特定的错误。
如果您查看 Instagram 的DOM Tree:
css 包含对 react-root
的引用<style type="text/css" data-isostyle-id="786433">#react-root,article,div,footer,header,main,nav,section{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;border:0 solid #000;-webkit-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;margin:0;padding:0;position:relative}</style>
<body>
以<span>
标记开头,其中包含 react-root ,如下所示:
<span id="react-root">
因此您的Locator Strategies基于这些动态类,例如v1Nh3
,kIKUG
,_bz0w
,_0mzm-
等,在 Test Execution < / em>。
一种适当的解决方案是根据HTML DOM中存在的 satic元素使用定位策略。
例如,在 Instagram弹出通知上以文本为不立即的元素上click()
的示例,您可以使用以下解决方案:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(.,'Not Now')]"))).click()
您可以在Click ''Not now" on Instagram notifications ask using Selenium and Python
中找到详细的讨论