Я пишу сценарий 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&post_id=7836284732687326&story_dom_id=u_fetchstream_3_o&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&surface=group_post_chevron&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 Удалить код ссылки на сообщение
Любая помощь приветствуется! Ваше здоровье!






Вы выглядите как 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 ()
Я не уверен, какой xpath вы используете для поиска ключа удаления. Не могли бы вы добавить больше HTML к своему вопросу (пожалуйста, не используйте изображение)? С правильным форматированием, чтобы я мог построить для вас хороший путь.
Я просто отредактировал вопрос, чтобы добавить код. Как вы думаете, мой Xpath не подходит? Я получаю Xpath, копируя ссылку из инспектора Chrome, есть возможность скопировать Xpath. Цените ваши усилия, чтобы помочь, большое спасибо!
Когда вы щелкаете по кнопке, которая открывает меню для выбора удаления, у вас есть элемент выше с этим class = "uiContextualLayerPositioner uiLayer"?
Когда у вас открыт инспектор, и вы нажимаете кнопку, чтобы открыть меню, вы должны увидеть дерево меню в изменении dom, можете ли вы дать мне весь HTML-код из div, который изменяется при нажатии кнопки, чтобы открыть меню вниз через опцию удаления?
Или просто все HTML от элемента выше id = "post_menu" и до удаления? Я пытаюсь воссоздать ваш сценарий, и мне трудно, потому что у меня нет вашего точного HTML. Я думаю, что знаю, что вызывает эту проблему.
Как вы думаете, в чем проблема? Я не могу снова отредактировать исходное сообщение, но я скопировал HTML-код из элемента выше id = "post_menu" в удаленное место и сохранил его здесь: pasted.co/dec01c4b
Хорошо, я обновил XPATH тем, что, по моему мнению, должно решить вашу проблему, но я считаю, что это потому, что есть несколько элементов с одним и тем же XPATH, которые являются СКРЫТЫЙ, которые вызывают проблему, с переходом к элементу выше и выбором классом, который не Включи hidden_elem в свой класс, должно работать.
Будет ли работать, если вы добавите разрыв перед строкой
delete =и позволите ей сначала загрузиться, а затем продолжить выполнение кода?