当前位置: 首页 > article >正文

028.爬虫专用浏览器-抓取#shadowRoot(closed)下的内容

一、什么是Shadow DOM

  • Shadow DOM是一种在web开发中用于封装HTML标记、样式和行为的技术,以避免组件间的样式和脚本冲突。
  • 它允许开发者将网页的一部分隐藏在一个独立的作用域内,从而实现更加模块化和可维护的代码结构

二、js操作Shadow DOM

// 获取宿主元素
const host = document.getElementById('main');

// 创建一个Shadow Root
const shadowRoot = host.attachShadow({mode: 'open'});

// 在Shadow DOM中添加内容
shadowRoot.innerHTML = `<style>:host { display: block; }</style><p>Hello, Shadow DOM!</p>`;

// 访问Shadow DOM中的内容
const shadowContent = host.shadowRoot.querySelector('p').textContent;
console.log(shadowContent); // 输出: Hello, Shadow DOM!

注意:这里attachShadow函数的mode参数有2种,open和closed。

  • 当mode设置为open时,Shadow DOM是相对开放的。这意味着外部的JavaScript代码可以通过宿主元素的shadowRoot属性访问Shadow DOM。这种访问权限允许开发者读取和修改Shadow DOM的结构和内容。
  • 当mode设置为closed时,Shadow DOM对外部JavaScript是不可访问的。这意味着宿主元素的shadowRoot属性在外部代码中将会返回null,从而无法直接访问或操作Shadow DOM的内容。

三、如何获取closed的shadowRoot里的内容

  • 网络上的数据如果不想让我们获取的话,一定是会使用closed模式,让我们无法js访问。

在这里插入图片描述

  • 但这里我们现在就是要获取closed的数据里面的内容怎么办呢?这里我提供一个解决方案:修改chromium源码,使shadowRoot的mode强行变为open。
1.找到源码:
  • 打开:\third_party\blink\renderer\core\dom\element.cc

  • 找到:

ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
                                  ExceptionState& exception_state) {
  DCHECK(shadow_root_init_dict->hasMode());
  String mode_string = shadow_root_init_dict->mode();
2.替换为:
ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
                                  ExceptionState& exception_state) {
  DCHECK(shadow_root_init_dict->hasMode());
  //String mode_string = shadow_root_init_dict->mode();
  mode_string = "open";
3.编译:
ninja -C out/Default chrome

编译完成后,可以发现所有的shadowRoot状态全部变成open啦。

四、还可以优化

  • 由于有些站会做反爬检测,如果发现shadowRoot返回的不是null后,就返回一些错误信息。
  • 这里我的优化思路是给Element新增一个魔改后的shadowRoot2属性,这样网站继续检测shadowRoot是不会有问题啦,有人关注的话会再补,没人关注就不写了。
  • 励志做个好用的爬虫浏览器。

http://www.kler.cn/news/363981.html

相关文章:

  • 解决url含%导致404错误
  • js(深浅拷贝,节流防抖,this指向,改变this指向的方法)
  • 蚁剑连接本地木马文件报错
  • vue-element-admin顶部导航栏的修改
  • 在 VS Code 中轻松绘图:Draw.io Integration 插件详解
  • [LeetCode] 230. 二叉搜索树中第K小的元素
  • C#与C++交互开发系列(九):字符串传递的几种形式
  • 执行Django项目的数据库迁移命令时报错:(1050, “Table ‘django_session‘ already exists“);如何破?
  • 【spring cloud】深入探讨 集群,分布式,微服务
  • OpenGL 进阶系列05 - OpenGL 图元重启(primitiverestart)
  • python的散列类型与字符编码
  • 为什么说Tcp是面向字节流的以及(Tcp粘包问题、TCP/UDP对比、listen函数的backlog参数的意义)
  • Kafka高可用性原理深度解析
  • 信息安全工程师(69)数字水印技术与应用
  • k8s-service详解
  • 使用python,自动实现将多个 JPG 文件转换为一个 PDF 文件
  • 11106 操作(c)
  • 【动态规划】子序列问题(上)
  • yarn的安装与使用以及与npm的区别(安装过程中可能会遇到的问题)
  • 动态规划-动归基础
  • 基于neo4j的新冠治疗和新冠患者轨迹的知识图谱问答系统
  • Hallo2 长视频和高分辨率的音频驱动的肖像图像动画 (数字人技术)
  • k8s 配置私有镜像仓库认证
  • repo将每个仓库回退到第一个commit的状态
  • 工具_Nginx
  • 学习记录:js算法(七十四):跳跃游戏II