Python Selenium Webdriver - невозможно найти элемент при удалении сообщения Facebook

Я пишу сценарий Python, который поможет мне удалить лишние сообщения в группе facebook с помощью Selenium Webdriver, и я столкнулся с проблемой, когда Selenium не может найти элемент.

Я получаю следующую ошибку:

selenium.common.exceptions.NoSuchElementException: 
Message: no such element: Unable to locate element: 
{"method":"xpath","selector":"//*[@id = "post_menu"]/div/ul/li[10]/a"}

Мой код выглядит так:

import os
import string
import time
import requests
import config
import re
import random
from tinytag import TinyTag
from clint.textui import progress
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
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.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome()
browser.implicitly_wait(60)

browser.get("https://www.facebook.com/groups/group_id/yourposts/?availability=available&referral_surface=your_posts_unsold_notif")
browser.maximize_window()
time.sleep(3)

browser.find_element_by_id("email").send_keys("email")
browser.find_element_by_id("pass").send_keys("password")
print("Logging in ...")

browser.find_element_by_id("loginbutton").click()
print("Logged in ...")

mainWindowHandle = browser.window_handles
print "main window handle: %s" %mainWindowHandle

elements = browser.find_elements_by_xpath('//*[contains(@id, "mall_post_")]')
for element in elements:
  allWindowsHandlesList = browser.window_handles
  print "all window handles: %s" %allWindowsHandlesList

  id = element.get_attribute("id")[10:]
  link_x_path = "//*[@id='mall_post_%s']/div/div[1]/a" % (id)
  link = browser.find_element_by_xpath(link_x_path)
  actions = ActionChains(browser)
  actions.move_to_element(link).perform()

  time.sleep(4)
  link.click()

  delete = browser.find_element_by_xpath('//*[@id = "post_menu"]/div/ul/li[10]/a')
  delete.click()

Проблема возникает, когда я пытаюсь найти ссылку Удалить, которая, вероятно, загружена Javascript:

delete = browser.find_element_by_xpath('//*[@id = "post_menu"]/div/ul/li[10]/a')

Это li, который содержит ссылку, я получаю Xpath, копируя ссылку из инспектора Chrome, есть возможность скопировать Xpath.

<li class = "_54ni _41t6 __MenuItem" role = "presentation">
<a class = "_54nc" href = "#" rel = "async-post"
ajaxify = "/ajax/groups/mall/delete/?group_id=874536857643876&amp;post_id=7836284732687326&amp;story_dom_id=u_fetchstream_3_o&amp;entstory_context=%7B%22last_view_time%22%3A1532623110%2C%22fbfeed_context%22%3Atrue%2C%22location_type%22%3A3%2C%22outer_object_element_id%22%3A%22u_fetchstream_3_o%22%2C%22object_element_id%22%3A%22u_fetchstream_3_o%22%2C%22is_ad_preview%22%3Afalse%2C%22is_editable%22%3Afalse%2C%22mall_how_many_post_comments%22%3A2%2C%22bump_reason%22%3A0%2C%22enable_comment%22%3Afalse%2C%22story_width%22%3A502%2C%22tn-str%22%3A%22-R%22%7D&amp;surface=group_post_chevron&amp;location=3" role = "menuitem">
<span><span class = "_54nh">
<div class = "_41t5">
<i class = "_41t7 img sp_PBbYkTGVdjY_2x sx_92b175"></i>
<i class = "_41t8 img sp_4Wahr7NwMMo_2x sx_7864af"></i>
Delete post</div></span></span></a>
</li>

После нажатия указанной выше ссылки откроется всплывающее окно с вопросом, уверены ли вы, что хотите удалить публикацию, и это кнопка Удалить, которую нужно нажать:

<button value = "1" class = "_42ft _4jy0 layerConfirm uiOverlayButton _4jy3 _4jy1 selected _51sy" data-testid = "delete_post_confirm_button" type = "submit">Delete</button>

Ссылка выглядит так:

facebook удалить ссылку на публикацию

Код в инспекторе Google Chrome выглядит так:

Инспектор Google Chrome Удалить код ссылки на сообщение

Любая помощь приветствуется! Ваше здоровье!

Будет ли работать, если вы добавите разрыв перед строкой delete = и позволите ей сначала загрузиться, а затем продолжить выполнение кода?

PixelEinstein 25.07.2018 20:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
827
1

Ответы 1

Вы выглядите как importingWebDriverWait, но не используете его. Если вы включите в свой сценарий правильные условия ожидания и замените вызовы time.sleep(), вы получите более согласованный сценарий селеном за работой.

Вот пример использования вашего кода выше:

NOTE: this code is untested, and built in Python 3, you appear to be using Python 2, but it should still work as is.

from selenium import webdriver
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.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)

browser.get("https://www.facebook.com/groups/group_id/yourposts/?availability=available&referral_surface=your_posts_unsold_notif")
browser.maximize_window()

wait.until(EC.visibility_of_element_located((By.ID, 'email'))).send_keys("email")
wait.until(EC.visibility_of_element_located((By.ID, 'pass'))).send_keys("password")
wait.until(EC.element_to_be_clickable((By.ID, 'loginbutton'))).click()
print("Logged in ...")

mainWindowHandle = browser.window_handles
print ("main window handle: %s" %mainWindowHandle)

elements = wait.until(EC.visibility_of_all_elements_located((By.XPATH, '//*[contains(@id, "mall_post_")]')))
for element in elements:
    allWindowsHandlesList = browser.window_handles
    print ("all window handles: %s" %allWindowsHandlesList)

    element_id = element.get_attribute("id")[10:]
    link_x_path = "//*[@id='mall_post_%s']/div/div[1]/a" % element_id
    link = wait.until(EC.visibility_of_element_located((By.XPATH, link_x_path)))
    actions = ActionChains(browser)
    actions.move_to_element(link).perform()
    wait.until(EC.element_to_be_clickable((By.XPATH, link_x_path))).click()

    #the wait here should resolve the AJAX load issue that caused your element to not be found    
    wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class = "uiContextualLayerPositioner uiLayer"]/div/div[@id = "post_menu"]/div/ul/li[10]/a'))).click()

Если все ваши локаторы верны, теперь вы сможете нажать кнопку удаления.

Это не решает проблему, а вызывает исключение TimeoutException на: wait.until (EC.element_to_be_clickable ((By.XPATH, '// * [@ id = "post_menu"] / div / ul / li [10] / a '))). click ()

NP1 26.07.2018 11:40

Я не уверен, какой xpath вы используете для поиска ключа удаления. Не могли бы вы добавить больше HTML к своему вопросу (пожалуйста, не используйте изображение)? С правильным форматированием, чтобы я мог построить для вас хороший путь.

PixelEinstein 26.07.2018 17:22

Я просто отредактировал вопрос, чтобы добавить код. Как вы думаете, мой Xpath не подходит? Я получаю Xpath, копируя ссылку из инспектора Chrome, есть возможность скопировать Xpath. Цените ваши усилия, чтобы помочь, большое спасибо!

NP1 26.07.2018 18:54

Когда вы щелкаете по кнопке, которая открывает меню для выбора удаления, у вас есть элемент выше с этим class = "uiContextualLayerPositioner uiLayer"?

PixelEinstein 26.07.2018 19:16

Когда у вас открыт инспектор, и вы нажимаете кнопку, чтобы открыть меню, вы должны увидеть дерево меню в изменении dom, можете ли вы дать мне весь HTML-код из div, который изменяется при нажатии кнопки, чтобы открыть меню вниз через опцию удаления?

PixelEinstein 26.07.2018 19:22

Или просто все HTML от элемента выше id = "post_menu" и до удаления? Я пытаюсь воссоздать ваш сценарий, и мне трудно, потому что у меня нет вашего точного HTML. Я думаю, что знаю, что вызывает эту проблему.

PixelEinstein 26.07.2018 19:25

Как вы думаете, в чем проблема? Я не могу снова отредактировать исходное сообщение, но я скопировал HTML-код из элемента выше id = "post_menu" в удаленное место и сохранил его здесь: pasted.co/dec01c4b

NP1 27.07.2018 18:18

Хорошо, я обновил XPATH тем, что, по моему мнению, должно решить вашу проблему, но я считаю, что это потому, что есть несколько элементов с одним и тем же XPATH, которые являются СКРЫТЫЙ, которые вызывают проблему, с переходом к элементу выше и выбором классом, который не Включи hidden_elem в свой класс, должно работать.

PixelEinstein 30.07.2018 19:40

Другие вопросы по теме