基于Selenium的Instagram私信Bot故障:无法点击点赞用户头像
解决Instagram点赞用户列表头像点击失败的Selenium脚本优化方案
问题根源分析
你的脚本无法点击点赞用户头像,核心原因包括:
- 元素定位偏差:原代码点击
<img>标签,但实际负责跳转的是其父级<a>标签,直接点击图片可能无法触发跳转逻辑。 - Stale元素引用:从用户主页返回点赞列表后,之前获取的元素引用已失效,无法再次交互。
- 等待逻辑不严谨:固定
sleep无法适配异步加载的弹窗,显式等待条件不够精准。
优化方案及代码修改
以下是针对性的优化步骤和修改后的完整代码:
1. 修正元素定位
直接定位点赞弹窗内的用户跳转链接(<a>标签),而非图片元素,确保点击的是实际可交互的节点。
2. 重新获取元素
每次从用户主页返回后,重新查询点赞列表的头像元素,避免StaleElementReferenceException。
3. 优化API初始化
每个账号仅初始化一次Instagram Private API,减少重复登录的性能开销。
4. 强化显式等待
针对点赞弹窗、头像元素等关键节点,使用更精准的显式等待条件替代固定sleep。
修改后的完整代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.firefox.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, StaleElementReferenceException import time from instagram_private_api import Client, ClientCompatPatch # 发送私信函数 def send_direct_message(api, user_id, message): api.direct_v2.send_direct_item( user_id=user_id, item_type='text', text=message ) # 从主页URL获取用户ID def get_user_id_from_url(api, profile_url): username = profile_url.split('/')[-2] user_info = api.username_info(username) return user_info['user']['pk'] # 账号凭据(替换为真实账号) account_credentials = { 'username1': 'password1', 'username2': 'password2', 'username3': 'password3' } # 初始化API def initialize_api(username, password): api = Client(username, password) return api # 每个账号要发送的私信数量 num_users_to_message = 5 # 初始化浏览器驱动 options = Options() options.headless = False driver = webdriver.Firefox(options=options) try: for username, password in account_credentials.items(): try: # 打开登录页 driver.get('https://www.instagram.com/accounts/login/') print(f"打开{username}的登录页") # 处理Cookie弹窗 try: allow_cookies_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//button[text()='Allow all cookies']")) ) allow_cookies_button.click() print("点击允许所有Cookie") WebDriverWait(driver, 5).until(EC.invisibility_of_element_located((By.XPATH, "//button[text()='Allow all cookies']"))) except TimeoutException: print("无Cookie弹窗或已关闭") # 登录 username_input = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.NAME, 'username')) ) password_input = driver.find_element(By.NAME, 'password') username_input.send_keys(username) password_input.send_keys(password) login_button = driver.find_element(By.XPATH, "//button[@type='submit']") login_button.click() print(f"正在登录{username}") WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.XPATH, "//span[text()='Home']")) ) print(f"{username}登录成功") # 打开目标帖子(替换为真实帖子URL) post_url = 'https://www.instagram.com/p/your_post_id/' driver.get(post_url) print(f"打开帖子:{post_url}") # 等待帖子加载完成 WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.XPATH, "//a[contains(@href, '/liked_by/')]")) ) # 打开点赞列表 try: likes_link = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "//a[contains(@href, '/liked_by/')]")) ) likes_link.click() print("打开点赞用户列表") # 等待点赞弹窗加载完成 likes_modal = WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'x1n2onr6') and contains(@role, 'dialog')]")) ) # 初始化当前账号的API(仅一次) api = initialize_api(username, password) sent_count = 0 while sent_count < num_users_to_message: try: # 重新获取当前页面的头像链接(避免stale元素) profile_links = WebDriverWait(likes_modal, 20).until( EC.presence_of_all_elements_located((By.XPATH, ".//a[starts-with(@href, '/') and @title]")) ) # 遍历未处理的用户 for link in profile_links[sent_count:]: if sent_count >= num_users_to_message: break try: # 等待链接可点击 WebDriverWait(driver, 10).until(EC.element_to_be_clickable(link)) link.click() print(f"点击第{sent_count+1}个用户头像") # 等待用户主页加载完成 WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.XPATH, "//h2")) ) # 获取用户信息并发送私信 user_username = driver.find_element(By.XPATH, "//h2").text user_id = get_user_id_from_url(api, driver.current_url) message_text = "Hello! This is an automated message." send_direct_message(api, user_id, message_text) print(f"已给{user_username}发送私信") sent_count += 1 # 返回点赞列表 driver.back() # 等待弹窗重新加载 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'x1n2onr6') and contains(@role, 'dialog')]")) ) except Exception as ex: print(f"处理用户时出错:{ex}") # 出错后回到点赞列表,继续下一个 driver.back() time.sleep(1) continue except StaleElementReferenceException: # 元素失效,重新获取弹窗 likes_modal = WebDriverWait(driver, 20).until( EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'x1n2onr6') and contains(@role, 'dialog')]")) ) continue print(f"{username}已完成{num_users_to_message}条私信发送") except TimeoutException: print("超时:未找到点赞链接") except TimeoutException as e: print(f"超时错误:{e}") finally: driver.quit()
额外注意事项
- Instagram会频繁更新页面结构,若后续定位失效,需重新检查元素的XPATH或Class属性。
- 避免过于频繁的操作,添加合理的等待间隔,防止账号被限制。
- 如需获取更多用户,可添加弹窗滚动逻辑:
driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", likes_modal)
内容的提问来源于stack exchange,提问作者Louis
相关产品推荐
相关产品推荐

