#python #selenium #selenium-webdriver #xpath
#python #selenium #selenium-webdriver #xpath
Вопрос:
Я работаю над разработкой программы, используя selenium
и python
, путем нажатия на серию сообщений (n = 235), начиная с самого старого (# 235), вплоть до самого нового (# 1). Пока что у меня есть его версия, которая частично выполняет то, что должна делать. Я говорю частично, потому что некоторых задач, которые я хочу включить в эту программу, еще нет (и у меня возникли проблемы с написанием кода).
Итак, то, что у меня есть на данный момент, — это программа, которая прокручивает страницу до конца, находит самое старое сообщение и нажимает на него.
Вот код
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
import time
#for i in range(1000):
lenOfPage = driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
match=False
while(match==False):
lastCount = lenOfPage
time.sleep(3)
lenOfPage = driver.execute_script("window.scrollTo(0, document.body.scrollHeight);var lenOfPage=document.body.scrollHeight;return lenOfPage;")
if lastCount==lenOfPage:
match=True
time.sleep(5)
totalLink=235#len(driver.find_elements_by_xpath("//div//div[1]//div[2]//ul[1]//li[3]//a[1]//i[1]"))
for i in range (1,totalLink-1):
linkxPath = "//div[" str(235-i 1) "]//div[1]//div[2]//ul[1]//li[3]//a[1]//i[1]"
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH,linkxPath))).click()
driver.execute_script("arguments[0].scrollIntoView();", driver.find_element_by_xpath(linkxPath))
#driver.find_element_by_xpath(linkxPath).click()
driver.find_element_by_xpath("//span[@class='share-title']").click()
#driver.refresh()
Проблемы:
- Мне не удалось включить функцию прокрутки вверх. Прямо сейчас, что я делаю, это обновляю страницу и прокручиваю ее до конца, затем нахожу самую старую запись и нажимаю на нее. Веб-страница, над которой я работаю, имеет такую особенность, что как только я нажимаю на более старую запись, эта запись становится новой (например, если я нажимаю на запись # 235, после обновления страницы она становится записью # 1).
- Я не смог придумать способ автоматизировать функцию щелчка, прямо сейчас у меня в коде есть 3 строки, в которых находятся элементы и щелчок по ним (не очень эффективно, потому что мне нужно обновить 235 сообщений, и я делаю это по 3 за раз). Просматривая элементы xpath, я заметил, что изменяется только одно число, но я не уверен, можно ли его изменить.
Элементы xpath:
//div[235]//div[1]//div[2]//ul[1]//li[3]//a[1]//i[1]
//div[234]//div[1]//div[2]//ul[1]//li[3]//a[1]//i[1]
.
.
.
//div[1]//div[1]//div[2]//ul[1]//li[3]//a[1]//i[1]
Ошибка
Traceback (most recent call last):
File "/home/pi/Documents/Posh_Auto.py", line 39, in <module>
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,linkxPath))).click()
File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/webelement.py", line 80, in click
self._execute(Command.CLICK_ELEMENT)
File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <i class="icon share-gray"></i> is not clickable at point (860, 8). Other element would receive the click: <div aria-expanded="false" aria-haspopup="true" class="dropdown-toggle" data-toggle="dropdown">...</div>
(Session info: chrome=78.0.3904.108)
Пожалуйста, дайте мне знать ваши мысли и комментарии.
Спасибо
Комментарии:
1. «//div[» i «]//div[1]//div[2] //ul[1] //li[3] //a[1] //i[1]» будет работать в цикле for.
2. На каком веб-сайте вы используете selenium?
Ответ №1:
driver.get("https://poshmark.com/closet/alyssascott688?sort_by=added_descamp;just_in_closet=true")
# Waiting for Page to load successfully
WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, "//img[@title='poshmark-logo']")))
# Since page is loading new elements after each scroll to bottom
# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
# Scroll down to bottom
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(2)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
shareLinks = driver.find_elements_by_xpath("//i[@class='icon share-gray']")
#Total such share link
print(len(shareLinks))
for i in range(1, len(shareLinks) 1):
xpathLink = "(//i[@class='icon share-gray'])[" str(226-i 1) "]"
#Creating Fresh elements so won't get stale element exception
clickLink = driver.find_element_by_xpath(xpathLink)
#Scroll to element and click
driver.execute_script("arguments[0].scrollIntoView();", clickLink)
driver.execute_script("arguments[0].click();", clickLink)
#After clicking on Share Link, I am copying the link. You can perform any other action if you want
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.XPATH, "//i[@class='icon copy-white']"))).click()
# To insure which link its clicking, I am printing link number
print("copied : " str(226-i 1))
# Waiting for links to be clickable before go to next
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.XPATH, xpathLink)))
Комментарии:
1. Я думаю, вы должны сначала получить размер и повторить цикл столько раз и использовать индекс размера, чтобы каждый раз нажимать на //div[235] / div [1] //div [2] //ul [1] //li[3] //a [1] // i [1] и обновлять. LinkxPath всегда должен быть последним.
2. @Perro Я не понял вашего вопроса? Вы говорите, что он щелкнул в первый раз, но не смог щелкнуть второй раз и далее? Также, как вы упомянули, после каждого обновления, когда div [235] становится div [1], так что происходит с последующими разделениями? В идеале в таком случае ваш последний div снова станет div [235]. В таких сценариях, как предложено Arundeep, linkXpath всегда должен быть путем к div [235]. Пожалуйста, дайте мне знать, хотите ли вы после обновления всегда нажимать на последнюю ссылку?
3. @rahulrai извините, мой вопрос был неясен. Я обновил свой код в сообщении. Проблема в том, что он выполняет действие щелчка только один раз, затем я получаю сообщение об ошибке. Вы правы, моя идея состоит в том, чтобы найти элемент (например, 235) click, а затем перейти к следующему (например, 234), чтобы он в конечном итоге добрался до первого элемента (который находится вверху страницы). Как только все это будет сделано, обновите страницу.
4. Попробуйте обновленный код. Он щелкнет все div [235], div [234] ….div [1].
5. @rahulrai еще раз благодарю вас за комментарии и помощь. Основываясь на вашем предложении, я изменил свой код. В результате моя программа теперь прокручивается до конца страницы и нажимает на элементы div [235], div [234] и div [233], к сожалению, когда приходит время прокручивать вверх, чтобы найти следующий элемент div [232], я получаю ошибку и (пожалуйста, обратитесь к исходному сообщению). У вас есть какие-либо идеи, почему это происходит?