You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:27:03