python - Python Selenium Webdriver - 删除 Facebook 帖子时无法找到元素
问题描述
我正在编写一个 Python 脚本来帮助我使用 Selenium Webdriver 删除多余的 facebook 群组帖子,但我遇到了 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,我通过从 Chrome 检查器复制链接来获取 Xpath,有一个复制 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>
链接如下所示:
Google Chrome Inspector 中的代码如下所示:
Google Chrome Inspector 删除帖子链接代码
任何帮助表示赞赏!干杯!
解决方案
您似乎是importing
WebDriverWait,但没有使用它。如果您在脚本中包含正确的等待条件,并替换您的time.sleep()
调用,您将拥有一个更加一致和有效的selenium 脚本。
这是使用上面代码的示例:
注意:此代码未经测试,并且是在 Python 3 中构建的,您似乎使用的是 Python 2,但它仍应按原样工作。
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()
只要您的所有定位器都是正确的,您现在应该能够单击删除按钮。
推荐阅读
- c# - 范围 Neo4j 驱动程序和会话对象
- c# - 如何在 Update 方法中修改 Start 方法变量:Unity
- gnuplot - 用 gnuplot 拟合 sinc 函数
- git - 如何使两个文件免受“都添加”的合并冲突?
- c++ - 做一些计数器操作,我该如何做,如果 setCounter() 没有参数,计数器为零?
- python - 如何在使用 python 写入 XML 文件时保留 XML 版本和注释?
- azure - 在 Azure Durable Functions Orchestator 中使用异步辅助函数是否安全?
- angular - 我想通过事件发射器为我的 html 输入设置值,并且在提交表单时这些值没有绑定。如何解决问题?
- c - 添加一段正常工作的代码时出现分段错误
- python-3.x - 模式识别和序列检测