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

如何用Python实现WalletConnect授权?Selenium连Metamask遇Shadow DOM问题

问题描述

我想通过WalletConnect将MetaMask连接到站点https://sendit.arcana.network/app/login,目前用Selenium做自动化操作,但页面存在Shadow DOM,无法点击MetaMask图标,希望通过已有的WalletConnect链接完成钱包连接。

WalletConnect链接:
wc:5f83a3ccbac958c359d6d176df0cd3ee506fb1a849246688ffc6cc9ca399026c@2?relay-protocol=irn&symKey=00b35938bf6b10e8a11cd2efc6df4c24bfc50f5f297f6031d85fef6e3eaf26a1

我的代码:

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from multiprocessing import Pool
from utils import proxy_utils
from seleniumwire import webdriver
import config

from fake_useragent import UserAgent


def main(thread):
    while True:
        try:
            def expand_shadow_element(element):
                shadow_root = driver.execute_script(f'return arguments[0].shadowRoot', element)
                return shadow_root
      
            # Driver Options
            options = webdriver.ChromeOptions()
            options.add_argument(f'user-agent={fake_useragent.UserAgent()}')
            options.add_extension('extensions/metamask.crx')

            options.add_argument('--disable-blink-features=AutomationControlled')
            options.add_argument('--log-level=3')
            options.add_experimental_option('excludeSwitches', ['enable-logging'])

            proxy_options = proxy_utils.proxy_options(config.use_proxys)

            s = Service('utils/chromedriver.exe')
            driver = webdriver.Chrome(service=s, seleniumwire_options=proxy_options, options=options)
            wait = WebDriverWait(driver, 30)

            driver.get("https://sendit.arcana.network/app/login")

            wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/main/main/div/div[2]/div[2]/div/section/section/section[2]/div/button')))

            driver.find_element(By.XPATH, '//*[@id="app"]/main/main/div/div[2]/div[2]/div/section/section/section[2]/div/button').click()

            root1 = driver.find_element(By.XPATH, '/html/body/w3m-modal[2]')
            shadow_root1 = expand_shadow_element(root1)

            root2 = shadow_root1.find_element(By.XPATH, '/div/div/w3m-modal-router')
            shadow_root2 = expand_shadow_element(root2[0])

        except Exception as error: print(f"Error: {error}")

        finally:
            try: driver.quit()
            except: pass

if __name__ == '__main__':
    with Pool(processes=config.threads) as pool:
        pool.map(main, range(config.threads))
解决方案

针对Shadow DOM无法点击MetaMask图标的问题,直接用WalletConnect链接完成连接的核心思路是绕过前端UI交互,直接调用连接逻辑,以下是两种可行方案:

方案一:直接注入WalletConnect连接逻辑

页面加载完成后,通过Selenium执行JavaScript代码,直接用给定的WalletConnect链接发起连接请求:

# 页面加载完成后执行以下代码
wc_link = "wc:5f83a3ccbac958c359d6d176df0cd3ee506fb1a849246688ffc6cc9ca399026c@2?relay-protocol=irn&symKey=00b35938bf6b10e8a11cd2efc6df4c24bfc50f5f297f6031d85fef6e3eaf26a1"

# 先动态引入WalletConnect SDK(如果页面未加载)
inject_sdk = """
const script = document.createElement('script');
script.src = 'https://unpkg.com/@walletconnect/client@2.10.1/dist/umd/index.min.js';
document.head.appendChild(script);
await new Promise(resolve => script.onload = resolve);
"""
driver.execute_script("async function loadSDK() {" + inject_sdk + "} loadSDK();")

# 发起连接请求
connect_script = f"""
const client = await window.WalletConnect.init({{ uri: "{wc_link}" }});
await client.connect();
"""
driver.execute_script("async function connect() {" + connect_script + "} connect();")

方案二:利用MetaMask扩展API处理连接

通过Selenium切换到MetaMask扩展页面,直接处理连接授权:

  1. 先获取MetaMask的扩展ID(Chrome扩展管理页面可查,默认ID为nkbihfbeogaeaoehlefnkodbefgpgknn)
  2. 切换到扩展页面完成授权:
# 切换到MetaMask扩展弹窗
metamask_id = "nkbihfbeogaeaoehlefnkodbefgpgknn"
driver.get(f"chrome-extension://{metamask_id}/popup.html")

# 等待授权按钮加载并点击(需根据实际页面元素调整定位)
wait.until(EC.element_to_be_clickable((By.XPATH, '//button[contains(text(), "确认")]'))).click()

注意:此方法需要提前确保MetaMask已解锁并配置好目标账户。

备选:修复原Shadow DOM定位逻辑

如果仍想通过原UI交互完成,可修正Shadow DOM的定位代码,避免依赖绝对XPATH:

# 等待w3m-modal加载
root1 = wait.until(EC.presence_of_element_located((By.TAG_NAME, 'w3m-modal')))
shadow_root1 = expand_shadow_element(root1)

# 获取w3m-modal-router的shadow root
root2 = shadow_root1.find_element(By.TAG_NAME, 'w3m-modal-router')
shadow_root2 = expand_shadow_element(root2)

# 定位并点击MetaMask按钮
metamask_btn = shadow_root2.find_element(By.XPATH, '//button[contains(@class, "w3m-wallet-button") and .//span[text()="MetaMask"]]')
metamask_btn.click()

内容的提问来源于stack exchange,提问作者Axcent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:08:10