使用Selenium定位Medium页面双击触发的隐藏弹窗并输入文本
使用Selenium与Medium.com上的作者交互
尝试用Selenium定位双击文本时触发的弹窗元素,识别并点击该元素后会在页面右侧打开消息框,最终目标是向该文本框中输入(send_keys)内容,目前操作遇到较大困难。


已尝试的方案代码
from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.keys import Keys def interact_with_author(message): # variables target_class = "meteredContent" body_css = "body" header_xpath = "/html/head" second_article_css = "#root > div > div.s.n.t > div.ah.ay > div > div.n.p > div > div:nth-child(2)" # the second article on the page first_par = "#\39 993" second_par = "#\35 f50" first_par_css = "#root > div > div.s > article > div > section > div > div > p" first_par_class = "ht hu dj hv b ei hw hx hy el hz ia ib ic id ie if ig ih ii ij ik il im in io db eg" wait_time = 5 # seconds to wait when sleep is called with the wait_time variable #code text_box = driver.find_element_by_css_selector('body > div:nth-child(47) > div > div > div > div > div') action = ActionChains(driver) listing=WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.TAG_NAME,"a"))) articles = driver.find_elements_by_tag_name("a") an_article = driver.find_element_by_css_selector(second_article_css) an_article.click() time.sleep(wait_time) # todo change to sleep four seconds after the article is fully loaded listing=WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.TAG_NAME,"p"))) try: paragraphs = driver.find_elements_by_tag_name('p') driver.execute_script("document.body.style.zoom='250%'") try: first_par = '' for i in range(1,len(paragraphs)): first_par_commentable = None try: first_par_commentable = driver.find_element_by_xpath(f"/html/body/div[1]/div/div[3]/article/div/section/div/div/p[{i}]") driver.execute_script("document.body.style.zoom='200%'") except Exception as e: ic(e) if first_par_commentable != None: break except Exception as f: ic(f) try: first_par_commentable.click() action.double_click(first_par_commentable).perform() time.sleep(random.randint(1,3)) except Exception as e: ic(e) except Exception as e: ic(e)
优化实现方案
原有方案的核心问题是使用了强依赖页面节点顺序的绝对路径选择器,Medium动态渲染时节点序号会频繁变化,同时缩放页面、依赖ActionChains坐标计算的逻辑容错性极低。
前置依赖导入
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time
优化后的交互函数
def interact_with_author(message): wait = WebDriverWait(driver, 15) # 等待第二篇文章可点击后跳转 second_article = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.n.p > div > div:nth-child(2) a"))) second_article.click() # 等待正文加载完成 wait.until(EC.presence_of_element_located((By.TAG_NAME, "article"))) time.sleep(2) # 定位首个正文段落 first_paragraph = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "article section p"))) # 通过JS触发双击,规避ActionChains坐标偏移问题 driver.execute_script(""" const dblclickEvent = new MouseEvent('dblclick', { bubbles: true, cancelable: true, view: window }); arguments[0].dispatchEvent(dblclickEvent); """, first_paragraph) # 等待高亮菜单的回应按钮加载,点击打开聊天框 reply_btn = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'highlightMenu')]//button[contains(@aria-label, 'Respond')]"))) reply_btn.click() # 定位文本输入框,输入目标内容 text_input = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='notesComposerInput']"))) text_input.send_keys(message)
方案优势
- 所有元素定位都基于Medium固定的测试属性、特征类名,完全不依赖节点顺序,适配平台动态渲染逻辑
- 全程使用显式等待替代固定sleep,执行效率和稳定性大幅提升
- JS触发双击的逻辑不受页面滚动、窗口大小变化的影响,容错性更高
- 可扩展能力强,调整段落、文章的定位规则即可适配不同的交互场景
内容的提问来源于stack exchange,提问作者Graham Waters
相关产品推荐
相关产品推荐

