python selenium(4+)+chromedriver最新版 定位爬取嵌套shadow-root(open)中内容

news2024/12/24 21:54:13

废话不多说,直接开始

本文以无界作为本文测试案例,抓取shadow-root(open)下的内容

shadow Dom in selenium

首先先讲一下shadow Dom in selenium 版本的区别,链接指向这里
在Selenium 4+版本 以及 chrome ver 96+中,有做出一下修改。摒弃了老版本的driver.find_element_by_css_selector。这点跟版本有关系,请自行查看目前使用的版本。

在这里插入图片描述

使用以及安装版本:

selenium 4.27.1 + chrome(131.0.6778.86)最新版本**
selenium pip install selenium==4.27.1即可(不指定版本也可以,目前默认安装此版本)
chromedriver 最新版本下载指向https://googlechromelabs.github.io/chrome-for-testing/#stable
由于selenium ,chrome+chromedriver 版本一直在迭代,所以也许过两年情况可能不一样了。具体更新见官方。

初入shadow-root:

先看shadow Dom in selenium提供的例子:

import os

import pytest
from selenium.webdriver import Chrome
from selenium.webdriver import Firefox
from selenium.webdriver import Remote
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.common.by import By


def test_old_code_old_chrome():
    """What most people use for Shadow DOM Elements.
    Still works for Chrome < v96, Edge < v96, Safari"""

    options = ChromeOptions()
    options.set_capability('browserVersion', '95.0')

    sauce_options = {'username': os.environ["SAUCE_USERNAME"],
                     'accessKey': os.environ["SAUCE_ACCESS_KEY"]}
    options.set_capability('sauce:options', sauce_options)

    sauce_url = "https://ondemand.us-west-1.saucelabs.com/wd/hub"

    driver = Remote(command_executor=sauce_url, options=options)

    driver.get('http://watir.com/examples/shadow_dom.html')

    shadow_host = driver.find_element_by_css_selector('#shadow_host')
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', shadow_host)
    shadow_content = shadow_root.find_element_by_css_selector('#shadow_content')

    assert shadow_content.text == 'some text'

    driver.quit()


def test_old_code_new_chrome():
    """Same code as above, but in Chromium 96+.
     Selenium 4.0 has same error as Selenium 3.
     Selenium 4.1 has AttributeError for using the old find_element_* method"""

    driver = Chrome()

    driver.get('http://watir.com/examples/shadow_dom.html')

    shadow_host = driver.find_element_by_css_selector('#shadow_host')
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', shadow_host)

    with pytest.raises(AttributeError, match="'ShadowRoot' object has no attribute 'find_element_by_css_selector'"):
        shadow_root.find_element_by_css_selector('#shadow_content')

    driver.quit()


def test_fix_old_code():
    """Same code as above, but using the new By class for find_element()
    This works in Selenium 4.1."""

    driver = Chrome()

    driver.get('http://watir.com/examples/shadow_dom.html')

    shadow_host = driver.find_element(By.CSS_SELECTOR, '#shadow_host')
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', shadow_host)
    shadow_content = shadow_root.find_element(By.CSS_SELECTOR, '#shadow_content')

    assert shadow_content.text == 'some text'

    driver.quit()


def test_recommended_code():
    """Please use this code."""

    driver = Chrome()

    driver.get('http://watir.com/examples/shadow_dom.html')

    shadow_host = driver.find_element(By.CSS_SELECTOR, '#shadow_host')
    shadow_root = shadow_host.shadow_root
    shadow_content = shadow_root.find_element(By.CSS_SELECTOR, '#shadow_content')

    assert shadow_content.text == 'some text'

    driver.quit()


def test_firefox_workaround():
    """Firefox is special."""

    driver = Firefox()

    driver.get('http://watir.com/examples/shadow_dom.html')

    shadow_host = driver.find_element(By.CSS_SELECTOR, '#shadow_host')
    children = driver.execute_script('return arguments[0].shadowRoot.children', shadow_host)

    shadow_content = next(child for child in children if child.get_attribute('id') == 'shadow_content')

    assert shadow_content.text == 'some text'

    driver.quit()

主要看test_recommended_code这部分代码,可以发现主要抓取some text,并assert
在这里插入图片描述
同理于是按照官方给的示例代码,很容易抓到“nested text

def test_recommended_code():
    """Please use this code."""

    driver = Chrome()

    driver.get('http://watir.com/examples/shadow_dom.html')

    shadow_host = driver.find_element(By.CSS_SELECTOR, '#shadow_host')
    shadow_root = shadow_host.shadow_root
    nest_shadow_host = shadow_root.find_element(By.CSS_SELECTOR, '#nested_shadow_host')
    nest_shadow_root = nest_shadow_host.shadow_root
    nest_shadow_content = nest_shadow_root.find_element(By.CSS_SELECTOR, '#nested_shadow_content')

    assert nest_shadow_content.text == 'nested text'

    driver.quit()

在控制台我们能得到同样的输出结果:
在这里插入图片描述
在这里插入图片描述

测试案例

打开本文开头指向的无界链接,进入F12。
在这里插入图片描述
这里主要看下,相比前一个简单例子的区别:

  1. 这里可以很明显看到wujie,这个词在之后抓取其他shadow-root网页会很常见。该测试案例网站也有介绍章节。
  2. shadow Dom内嵌<html>,同时注意到下方的script脚本,有些网站会写到是异步脚本动态加载js,该过程需要在selenium中使用 timesleep或者until 来解决动态加载问题。
    如下(异步加载js):在这里插入图片描述
    参考前一个例子来抓取仓库地址
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 设置 Chrome options
options = webdriver.ChromeOptions()
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36')

# 初始化 WebDriver
driver = webdriver.Chrome(options=options)
# 在页面中执行自定义 JavaScript 代码

try:
    # 打开目标网页
    url = "https://wujie-micro.github.io/demo-main-vue/vue3?vue3=%2Fdemo-vue3%2Fhome"
    driver.get(url)
    time.sleep(5)
    # 等待页面加载并找到目标元素所在的 Shadow DOM
    # wait = WebDriverWait(driver, 20)  # 等待最多20秒
    # shadow_host = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "wujie-app.wujie_iframe")))
    shadow_host = driver.find_element(By.CSS_SELECTOR,"wujie-app.wujie_iframe")
    shadow_root = shadow_host.shadow_root
    html_element = shadow_root.find_element(By.CSS_SELECTOR,'html')
    button = html_element.find_element(By.CSS_SELECTOR,".el-button")
    assert button.text == '仓库地址'

except Exception as e:
    print("Error:", e)

finally:
    driver.quit()

恭喜你,你会收到一份报错
在这里插入图片描述尝试F12控制台js获取,复制JS路径,控制台输出,说明没问题。
在这里插入图片描述
尝试在python selenium运行js

	#加不加return 返回都是none
    result = driver.execute_script(
        'return document.querySelector("#app > div.content > div > wujie-app").shadowRoot.querySelector("#app > div:nth-child(2) > div.content > p:nth-child(4) > button > span")')

result返回是none
在这里插入图片描述

于是就开始查这个问题查了大半天,百度 csdn,stackoverflow什么的翻了个底朝天,几乎一度快放弃了。。。。到这里以为是被反爬了,但后想了一想该网站应该不是一个商用的客户网站,不涉及到用户信息,应该不会有反爬才对,所以决定再试试。
实在不行了,打算去看看chromedriver的开源代码查查到底为什么,查之前抱着试一试的态度在chromedriver的 issue中搜我的问题竟然找到了解决办法!

只能说十分感谢该老哥!链接指向

感兴趣的可以去看源码,我自己后面去看了下里面这个IsNodeReachable,这里就不贴图分析了。
在这里插入图片描述
问题大概是 Shadow DOM 的封装性导致节点在 Chromedriver 的验证中被误判为不可达。
所以解决思路: 通过修改 Shadow DOM 节点的行为(伪装其父节点为全局文档),绕过验证逻辑。
于是修改后代码如下:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 设置 Chrome options
options = webdriver.ChromeOptions()
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36')

# 初始化 WebDriver
driver = webdriver.Chrome(options=options)
# 在页面中执行自定义 JavaScript 代码

try:
    # 打开目标网页
    url = "https://wujie-micro.github.io/demo-main-vue/vue3?vue3=%2Fdemo-vue3%2Fhome"
    driver.get(url)
    time.sleep(5)

    driver.execute_script("""
        Object.defineProperty(window.document.querySelector('wujie-app').shadowRoot.firstElementChild, "parentNode", {
            enumerable: true,
            configurable: true,
            get: () => window.document,
          });
    """)
    # 等待页面加载并找到目标元素所在的 Shadow DOM
    # wait = WebDriverWait(driver, 20)  # 等待最多20秒
    # shadow_host = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "wujie-app.wujie_iframe")))
    
    #方法1,直接复制js路径,更简单
    result = driver.execute_script(
        'return document.querySelector("#app > div.content > div > wujie-app").shadowRoot.querySelector("#app > div:nth-child(2) > div.content > p:nth-child(4) > button > span")')
        
	#方法2 一步步的,我个人感觉这样更清晰,对于初学,我建议这样层层递进,并学会
	# find_element(By.CSS_SELECTOR 的使用
    shadow_host = driver.find_element(By.CSS_SELECTOR,"wujie-app.wujie_iframe")
    shadow_root = shadow_host.shadow_root
    html_element = shadow_root.find_element(By.CSS_SELECTOR,'html')
    button = html_element.find_element(By.CSS_SELECTOR,".el-button")
    
    #方法2 Ans
    assert button.text == '仓库地址'
    #方法1 Ans
    assert result.text == '仓库地址'
    print(button.text)
    print(result.text)
except Exception as e:
    print("Error:", e)

finally:
    driver.quit()

最后成功拿到 仓库地址(好的,现在就偷仓库东西去了)
在这里插入图片描述

课后作业!

试试抓取 某企鹅下的 某moba手游论坛下的用户名,日期!
实验链接:彻底疯狂!

I got it ,代码和上述大差不差
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2255575.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1207论文速读

1、SCN_GNN: A GNN-based fraud detection algorithm combining strong node and graph topology information 全文总结&#xff1a;本文介绍了一种基于图神经网络的欺诈检测算法——SCN_GNN。在欺诈检测中&#xff0c;由于欺诈者经常使用多种关系类型来掩盖其活动&#xff0c…

5.3_小程序渗透

小程序 行为工具小程序抓包全局代理&#xff0c;Proxifer小程序渗透小程序反编译Wxapkg 参数&#xff1a;scan 联网自动扫描&#xff0c;-r 指定 wx文件路径小程序逆向WeChatOpenDevTools 小程序抓包 工具步骤 全局代理 Burp中Proxy setings导出证书选择 Select file &a…

怎么实现邮件营销自动化?

邮件营销能够出色地帮助我们与客户建立良好关系。无论是新客户还是老客户&#xff0c;都可以通过邮件来达成较为良好的客户关系。然而&#xff0c;从消费者的角度来看&#xff0c;每个人都有自己独特的习惯和特点&#xff0c;没有人希望收到千篇一律、营销意味过重的邮件。因此…

使用ensp搭建内外互通,使用路由跨不同vlan通信。

1.网络拓扑图 2.规则 &#xff08;1&#xff09;允许 &#xff08;自己&#xff09;ping通内外网&#xff0c;内外网随便一个pc就可以. &#xff08;2&#xff09; 允许&#xff08;电信&#xff09;ping通内外网&#xff0c;内外网随便一个pc就可以 &#xff08;时间问题不做…

鸿蒙分享(一):添加模块,修改app名称图标

码仓库&#xff1a;https://gitee.com/linguanzhong/share_harmonyos 鸿蒙api:12 新建公共模块common 在entry的oh-package.json5添加dependencies&#xff0c;引入common模块 "dependencies": {"common": "file:../common" } 修改app名称&…

自定义指令,全局,局部,注册

让输入框自动获取焦点(每次刷新自动获取焦点&#xff09; <template><div><h3>自定义指令</h3><input ref"inp" type"text"></div> </template><script> export default {mounted(){this.$refs.inp.focus…

【C语言】C语言的变量和声明系统性讲解

声明和定义的概念 在C语言中&#xff0c;**声明&#xff08;Declaration&#xff09;和定义&#xff08;Definition&#xff09;**是两个重要的基础概念&#xff0c;它们都涉及到变量、函数、结构体等的使用&#xff0c;但功能和作用存在明显区别&#xff1a; 声明&#xff1a…

【优选算法篇】:滑动窗口算法--开启高效解题的“窗口”,透过例题看奥秘

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;c篇–CSDN博客 文章目录 一.滑动窗口算法二.例题1.长度最小的子数组2.无重复字符的最长字串…

调用大模型api 批量处理图像 保存到excel

最近需要调用大模型&#xff0c;并将结果保存到excel中&#xff0c;效果如下&#xff1a; 代码&#xff1a; import base64 from zhipuai import ZhipuAI import os import pandas as pd from openpyxl import Workbook from openpyxl.drawing.image import Image from io i…

CEEMDAN-CPO-VMD二次分解(CEEMDAN+冠豪猪优化算法CPO优化VMD)

CEEMDAN-CPO-VMD二次分解&#xff08;CEEMDAN冠豪猪优化算法CPO优化VMD&#xff09; 目录 CEEMDAN-CPO-VMD二次分解&#xff08;CEEMDAN冠豪猪优化算法CPO优化VMD&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 首先运用CEEMDAN对数据进行一次分解&#xff…

Bloom 效果

1、Bloom 效果是什么 Bloom效果&#xff08;中文也可以叫做高光溢出效果&#xff09;&#xff0c;是一种使画面中亮度较高的区域产生一种光晕或发光效果的图像处理技术&#xff0c;Bloom效果的主要目的是模拟现实世界中强光源在相机镜头或人眼中造成的散射和反射现象&#xff…

【ArkTS】列表组件的“下拉刷新”和“上拉加载”

系列文章目录 【ArkTS】关于ForEach的第三个参数键值 【ArkTS】“一篇带你读懂ForEach和LazyForEach” 【小白拓展】 【ArkTS】“一篇带你掌握TaskPool与Worker两种多线程并发方案” 【ArkTS】 一篇带你掌握“语音转文字技术” --内附详细代码 【ArkTS】技能提高–“用户授权”…

Otter数据同步原理

otter是阿里巴巴的开源的一款数据数据同步工具&#xff0c;它基于对数据库增量日志解析&#xff0c;准实时同步到本机房或者异地机房的mysql/oracle/mq等&#xff0c;是一个分布式数据同步系统。otter第一版本可追溯到04~05年&#xff0c;开发时间从2011年7月份一直持续到现在&…

【已解决】黑马点评项目中-实战篇11-状态登录刷新章节设置RefreshTokenInterceptor拦截器后登录异常的问题

黑马点评项目中-实战篇11-状态登录刷新章节设置RefreshTokenInterceptor拦截器后登录异常的问题 在 MvcConfig 文件中添加好RefreshTokenInterceptor拦截器 出现异常情况 按照验证码登录后&#xff0c;进入主页面&#xff0c;再点击“我的”&#xff0c;又跳入登录界面 原因…

AI - RAG中的状态化管理聊天记录

AI - RAG中的状态化管理聊天记录 大家好&#xff0c;今天我们来聊聊LangChain和LLM中一个重要的话题——状态化管理聊天记录。在使用大语言模型(LLM)的时候&#xff0c;聊天记录&#xff08;History&#xff09;和状态&#xff08;State&#xff09;管理是非常关键的。那我们先…

记一次跑前端老项目的问题

记一次跑前端老项目的问题 一、前言二、过程1、下载依赖2、启动项目3、打包 一、前言 在一次跑前端老项目的时候&#xff0c;遇到了一些坑&#xff0c;这里记录一下。 二、过程 1、下载依赖 使用 npm install下载很久&#xff0c;然后给我报了个错 core-js2.6.12: core-js…

使用Goland对6.5840项目进行go build出现异常

使用Goland对6.5840项目进行go build出现异常 Lab地址: https://pdos.csail.mit.edu/6.824/labs/lab-mr.html项目地址: git://g.csail.mit.edu/6.5840-golabs-2024 6.5840运行环境: mac系统 goland git clone git://g.csail.mit.edu/6.5840-golabs-2024 6.5840 cd 6.5840/src…

Thonny IDE + MicroPython + ESP32 + GY-302 测量环境中的光照强度

GY-302是一款基于BH1750FVI光照强度传感器芯片的模块。该模块能够直接测量出环境中的光照强度&#xff0c;并将光照强度转换为数字信号输出。其具体参数如下表所示。 参数名称 参数特性 测量范围 0-65535 LX 测量精度 在环境光下误差小于20%&#xff0c;能够自动忽略50/60…

网站打开速度测试工具:互联网优化的得力助手

在信息飞速流转的互联网时代&#xff0c;网站如同企业与用户对话的窗口&#xff0c;其打开速度直接关乎用户体验&#xff0c;乃至业务的成败。所幸&#xff0c;一系列专业的网站打开速度测试工具应运而生&#xff0c;它们宛如幕后的技术侦探&#xff0c;精准剖析网站性能&#…

2024数字科技生态大会 | 紫光展锐携手中国电信助力数字科技高质量发展

2024年12月3日至5日&#xff0c;中国电信2024数字科技生态大会在广州举行&#xff0c;通过主题峰会、多场分论坛、重要签约及合作发布等环节&#xff0c;与合作伙伴共绘数字科技发展新愿景。紫光展锐作为中国电信的战略合作伙伴受邀参会&#xff0c;全面呈现了技术、产品创新进…