【JavaScript】读取商品页面中的结构化数据(JSON-LD),在不改动服务端情况下,实现一对一跳转

前端实践:从商品页面读取 mpn 并实现一对一跳转

在实际开发中,我们经常会遇到这样一种需求:
用户浏览 A 网站的商品页面后,点击按钮能够直接跳转到 B 网站的对应商品。

表面看似只是一个按钮跳转,但如果不同商品需要精确映射,就必须找到每个商品的唯一标识。这时,很多电商页面都会通过 结构化数据(JSON-LD) 提供关键信息,例如 mpn(Manufacturer Part Number,制造商零件号)。


1. 问题背景

  • 我需要在商品详情页中获取唯一标识 mpn,并基于它拼接目标商店的跳转链接。
  • 页面本身是第三方的,不能直接改动服务端返回的数据。
  • 目标效果:隐藏原始「加入购物车 / 立即购买」按钮,替换为一个自定义按钮,点击后跳转到另一个电商平台(例如 DHgate)的对应商品。

2. 数据获取的波折

一开始,我尝试直接在页面 DOM 中寻找 mpn

  • document.querySelector() 去找标签 → 失败
  • meta 标签里查找 → 失败
  • 在页面可见文本里搜索 → 失败

直到我注意到页面 <head> 区域存在大量 <script type="application/ld+json"> 标签,这是用于 SEO 的结构化数据。
里面通常包含:

{"@context": "https://schema.org/","@type": "Product","name": "Luxury Custom Handmade Watch","mpn": "123456789","brand": {"@type": "Brand","name": "Artisan Watches"}
}

注解:
JSON-LD(JavaScript Object Notation for Linked Data)是 Google 推荐的结构化数据标注方式。
电商网站会用它向搜索引擎说明商品属性,比如:名称、价格、库存、SKU、MPN 等。

这意味着 最佳的获取方式是解析 JSON-LD,而不是从 DOM 树中“扒值”。


3. 解决方案:解析 JSON-LD 提取 mpn

代码实现如下:

// 获取所有 JSON-LD 脚本标签
const ldJsonScripts = document.querySelectorAll('script[type="application/ld+json"]');let mpnValue = null;// 遍历解析 JSON,找到 Product 类型的 mpn
ldJsonScripts.forEach(script => {try {const jsonData = JSON.parse(script.textContent);if (jsonData["@type"] === "Product" && jsonData.mpn) {mpnValue = jsonData.mpn;}} catch (e) {console.error("解析 JSON-LD 出错:", e);}
});

这样就能稳健地提取出 mpn 值。


4. 替换默认按钮并添加跳转逻辑

由于目标是 一对一跳转,我需要屏蔽原有的购物入口,改为跳转到目标链接。

4.1 隐藏原有按钮

原始按钮 ID 具有统一前缀(如 add-cart-xxxbuynow-xxx),所以通过前缀匹配批量隐藏:

function hideElementsWithPrefix(prefix) {const allElements = document.getElementsByTagName('*');for (let element of allElements) {if (element.id && element.id.startsWith(prefix)) {element.style.display = 'none';}}
}

并且定时执行,防止异步加载的按钮漏网:

setInterval(() => {hideElementsWithPrefix('add-cart-');hideElementsWithPrefix('buynow-');
}, 1000);

4.2 添加自定义按钮

const customButton = document.createElement('button');
customButton.textContent = 'Buy Now on DHgate';
customButton.style.cssText = `background-color: #D4AF37;color: white;border: none;padding: 12px 24px;font-size: 16px;font-weight: bold;border-radius: 6px;cursor: pointer;margin: 10px 0;transition: background-color 0.3s ease;
`;// 悬停效果
customButton.addEventListener('mouseover', () => customButton.style.backgroundColor = '#C89A2E');
customButton.addEventListener('mouseout', () => customButton.style.backgroundColor = '#D4AF37');// 点击跳转
customButton.addEventListener('click', () => {const targetUrl = `https://www.dhgate.com/product/french-artisanal-luxury-exquisite-custom/${mpnValue}.html?`;window.location.assign(targetUrl);// 备份方案:防止 assign 失败setTimeout(() => {if (window.location.href !== targetUrl) {window.location.href = targetUrl;}}, 100);
});

插入到页面:

const insertionPoint = document.querySelector('.product-cart-group') ||document.querySelector('.main_btn').parentNode ||document.body;insertionPoint.appendChild(customButton);

5. 最终效果

  • 页面原有的「加入购物车 / 立即购买」按钮被隐藏。
  • 出现一个新的金色按钮 “Buy Now on DHgate”
  • 点击时,根据当前页面解析到的 mpn 值,自动拼接跳转链接并跳转。

例如:

https://www.dhgate.com/product/french-artisanal-luxury-exquisite-custom/123456789.html

非常好 👍
你提到的这一点非常关键:作为后端,很多人会觉得前端拿个值“应该很简单”,但实际落到细节上,经常会踩坑。
你经历 mpn 的抓取,就是一个典型的前端数据获取思路问题。

下面我以“从一个商品页面获取关键数据”为引,系统整理前端常见的数据抓取手段,带例子和注解。


前端数据抓取手段

前端里,想要拿到一个页面的数据,不一定总是 document.querySelector("#id") 那么直白。


1. 直接 DOM 查询

最直观的方法就是 通过选择器直接查找元素

// 通过 ID
const price = document.querySelector("#product-price").textContent;// 通过 class
const title = document.querySelector(".product-title").innerText;// 通过标签层级
const stock = document.querySelector("div.product-info span.stock").innerText;

注解:

  • 如果页面是 SSR(服务端渲染),DOM 一开始就有数据,这是最快捷的方式。
  • 但对于 SPA(单页应用),很多内容是后续 JS 渲染的,需要等 window.onloadMutationObserver

2. 结构化数据(JSON-LD、Microdata、RDFa)

之前遇到的 mpn,就是嵌在 <script type="application/ld+json"> 里的。

const scripts = document.querySelectorAll('script[type="application/ld+json"]');
scripts.forEach(s => {try {const json = JSON.parse(s.textContent);if (json["@type"] === "Product") {console.log(json.mpn, json.sku, json.brand?.name);}} catch (e) {}
});

注解:

  • 这种方式对 SEO 友好,Google / Bing / 电商比价插件都会用。
  • 如果在做 商品比对 / 跨站跳转 / 爬虫,这是最可靠的切入点。

3. 隐藏在 meta 标签 / 属性中

一些页面会把关键数据放在 <meta>data-* 属性里,给搜索引擎或前端脚本用。

例子:meta 标签

<meta property="product:price:amount" content="99.99">
<meta property="product:sku" content="A12345">

获取:

const price = document.querySelector('meta[property="product:price:amount"]').content;
const sku = document.querySelector('meta[property="product:sku"]').content;

例子:data-* 属性

<button id="buyBtn" data-sku="A12345" data-stock="20">Buy Now</button>

获取:

const btn = document.getElementById("buyBtn");
console.log(btn.dataset.sku);   // "A12345"
console.log(btn.dataset.stock); // "20"

注解:

  • data-* 是 HTML5 规范推荐的“私有数据通道”,比 id / class 更稳定。
  • 在电商、新闻站、CMS 里很常见。

4. 页面内嵌 JSON 配置(window 变量 / inline script)

有些网站在 <script> 里会直接挂一个全局对象,供页面其他 JS 使用。

例子:

<script>window.__INITIAL_STATE__ = {product: {id: "12345",name: "Luxury Watch",price: 299.99,mpn: "XYZ987"}};
</script>

获取:

console.log(window.__INITIAL_STATE__.product.mpn);

注解:

  • SPA 框架(React/Vue/Next.js)经常这么做,把后端数据注入到页面里。
  • 在 f12 → Console 输入 window,多翻几页,常能挖到完整的数据结构。

5. Ajax / Fetch 请求拦截

很多页面并不是直接渲染,而是前端在加载时通过 Ajax/FETCH 请求接口。
这类数据可以直接抓接口,而不是“扒 DOM”。

例子:

商品页打开时,浏览器可能会请求:

GET https://api.shop.com/product/12345

返回:

{"id": "12345","title": "Luxury Watch","price": "299.99","mpn": "XYZ987"
}

在前端可以这样拦截:

// 重写 fetch
const originalFetch = window.fetch;
window.fetch = async (...args) => {const response = await originalFetch(...args);if (args[0].includes("/product/")) {response.clone().json().then(data => {console.log("抓到商品数据:", data);});}return response;
};

注解:

  • 这是 最稳定 的方案,因为你直接拿到原始 JSON 数据。
  • 后端开发者更熟悉接口,所以只要能找到 API 请求,比 DOM 抓取更靠谱。
  • 在 DevTools → Network 里找 XHR / Fetch,常能发现目标接口。

6. 监听 DOM 变化(MutationObserver)

如果页面异步渲染(比如 React/Vue 延迟加载),DOM 里可能一开始没有数据。
这时需要用 MutationObserver 来监听节点变化。

const observer = new MutationObserver(mutations => {const priceNode = document.querySelector(".product-price");if (priceNode) {console.log("价格:", priceNode.textContent);observer.disconnect(); // 拿到后停止监听}
});observer.observe(document.body, { childList: true, subtree: true });

注解:

  • 适合异步加载的 SPA。
  • setInterval 更优雅,但逻辑复杂一些。

7. Canvas / Shadow DOM / 加密数据(特殊情况)

一些网站会反爬虫,把数据写在:

  • Canvas 渲染出来(你只能截图识别)
  • Shadow DOM(需要穿透 .shadowRoot
  • Base64 / 加密字符串(要解码/解密)

这种情况属于“反爬虫”范畴,日常不常见,但电商/金融站点有时会遇到。


总结

方法特点适用场景难度
DOM 选择器直观,容易写静态页面、SSR
JSON-LD / Microdata结构化,标准化商品详情、SEO 站点⭐⭐
meta / data-*隐藏但容易读电商、CMS⭐⭐
window 全局变量完整数据,格式化React/Vue 注水页面⭐⭐
Ajax / Fetch原始 JSON,最稳定SPA、电商 API⭐⭐⭐
MutationObserver处理异步渲染Vue/React 延迟加载⭐⭐⭐
Canvas / Shadow DOM反爬虫用金融、电商防护⭐⭐⭐⭐

建议的思路是:

  1. 优先找 API(最干净的 JSON);
  2. 找不到 API → 看 JSON-LD / meta / data-*;
  3. 再不行 → 扫 window 全局变量;
  4. 实在没有 → MutationObserver、模拟渲染、甚至 OCR。

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

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

相关文章

HTML5实现好看的邀请函网页源码

HTML5实现好看的邀请函网页源码 前言一、设计来源1.1 邀请函主页1.2 邀请函活动信息1.3 邀请函内容1.4 邀请函活动地址1.5 邀请函活动流程1.6 邀请函活动奖励1.7 邀请函联系我们 二、效果和源码2.1 动态效果2.2 源代码 结束语 HTML5实现好看的邀请函网页源码&#xff0c;酷炫的…

传输层TCP 与 安全层SSL/TLS

本章节主要探讨三个问题&#xff1a;1. SSL/TSL 的区别和联系是什么&#xff1f;2. 我们常说的 “三次握手” 发生在哪个阶段&#xff0c;SSL/TSL层有参与吗?3. HTTPS混合加密发生在哪个层?一、SSL 和 TLS 联系继承关系&#xff1a;TLS 直接基于 SSL 3.0 设计&#xff0c;可以…

【数学建模学习笔记】时间序列分析:ARIMA

零基础看懂 ARIMA 模型&#xff1a;从原理到实战如果你完全没接触过 “时间序列预测”&#xff0c;也不懂复杂公式&#xff0c;这篇会用 “说人话” 的方式帮你搞懂 ARIMA 模型&#xff0c;以及文中代码到底在做什么。一、先搞懂&#xff1a;ARIMA 是用来干嘛的&#xff1f;简单…

【macOS】垃圾箱中文件无法清理的“含特殊字符文件名”的方法

【macOS】垃圾箱中文件无法清理的“含特殊字符文件名”的方法文件名包含特殊字符&#xff08;如空格、中文符号等&#xff09;导致终端无法正确识别文件路径。 可以尝试以下解决方法&#xff1a;使用文件路径自动补全输入 rm &#xff08;注意 rm 后有空格&#xff09;&#xf…

​​​​​​​Blender 重拓扑修改器实战指南:从基础操作到细节优化​

在 Blender 建模中&#xff0c;重拓扑是解决 “高模难编辑、低模细节差” 的关键。传统手动重拓扑效率低&#xff0c;重拓扑修改器能自动生成规整拓扑&#xff0c;保留模型外形&#xff0c;适合游戏资产、动画角色等场景。 一、核心作用与适用场景​ 重拓扑修改器并非 “一键完…

C/C++哆啦A梦

写在前面 用代码绘制童年记忆中的那个蓝胖子——哆啦A梦&#xff0c;是我对经典角色的一次深情致敬。这段程序不仅是一幅静态图像的生成&#xff0c;更是一次对童年幻想世界的数字重建。通过精确的几何控制与色彩搭配&#xff0c;我将那个圆润可爱、温暖可靠的机器人重新带回眼…

CSS入门指南:30字掌握核心技巧

1. CSS初体验 1.1. CSS定义 层叠样式表 (Cascading Style Sheets&#xff0c;缩写为 CSS&#xff09; 用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09; 1.2. CSS引入方式 内部样式表&#xff1a;学习使用 CSS 代码写在head里面的 style标签 里面 外部样式表&…

从实操到原理:一文搞懂 Docker、Tomcat 与 k8s 的关系(附踩坑指南 + 段子解疑)

目录 一、先分清&#xff1a;Docker、Tomcat、k8s 到底是 “干啥的”&#xff1f; 二、它们的 “合作关系”&#xff1a;从 Java 项目到集群部署的全流程 三、实际应用场景&#xff1a;什么时候该用谁&#xff1f; 1. 单独使用场景 2. 组合使用场景&#xff08;最常见&…

测试覆盖率不够高?这些技巧让你的FastAPI测试无懈可击!

url: /posts/0577d0e24f48b3153b510e74d3d1a822/ title: 测试覆盖率不够高?这些技巧让你的FastAPI测试无懈可击! date: 2025-09-02T01:49:10+08:00 lastmod: 2025-09-02T01:49:10+08:00 author: cmdragon summary: FastAPI通过TestClient工具支持单元测试,模拟HTTP请求直接…

Qwen3-Reranker-0.6B 模型结构

模型加载 import torch from modelscope import AutoModel, AutoTokenizer, AutoModelForCausalLMtokenizer AutoTokenizer.from_pretrained("Qwen/Qwen3-Reranker-0.6B", padding_sideleft) model AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-Reranke…

无参 MOS 算法的评估方式

一、无参 MOS 算法 在音频处理和质量评估领域&#xff0c;MOS&#xff08;Mean Opinion Score&#xff09;是一种常用的主观评价指标&#xff0c;用于衡量音频质量。然而&#xff0c;获取主观 MOS 评分通常需要大量的人力和时间。因此&#xff0c;无参 MOS 算法应运而生&#…

Flowable——配置使用Flowable-UI

文章目录 前言 框架选型与版本 flowable-ui 搭建 依赖引入 springboot 主要版本 flowable 相关 log4j 日志配置项 配置文件 log4j配置文件 application.yml 增加启动类并启动程序 项目整体结构 前言 最近对工作流的flowable比较感兴趣,汇总记录一下相关的研究学习知识点。 框…

2025大学生必考互联网行业证书排名​

在互联网行业蓬勃发展的当下&#xff0c;大学生若想毕业后顺利投身其中&#xff0c;提前考取相关高含金量证书不失为明智之举。这些证书不仅能证明专业能力&#xff0c;还能在求职时为你增添竞争优势。接下来&#xff0c;为大家详细介绍 2025 年大学生必考的互联网行业证书排名…

【并发系列-01】高并发系统架构设计原理

【并发系列-01】高并发系统架构设计原理 1. 业务场景&#xff1a;当双11遇上技术挑战 1.1 问题场景描述 想象一下这样的场景&#xff1a;某电商平台在双11期间&#xff0c;短短30分钟内涌入了500万用户&#xff0c;同时发起了超过2000万次商品查询请求和100万次下单操作。而平时…

【Vue2 ✨】Vue2 入门之旅(八):过渡与动画

前几篇我们学习了事件处理。本篇将介绍 过渡与动画&#xff0c;让 Vue 页面更加生动。 目录 transition 组件进入与离开过渡过渡类名结合 CSS 动画JavaScript 钩子小结 transition 组件 Vue 提供了内置组件 <transition>&#xff0c;可以为元素或组件的进入和离开添加动…

【LeetCode】力扣刷题攻略路线推荐!适合新手小白入门~(含各类题目序号)

力扣上有许多数据结构及算法的练习&#xff0c;但是如果由第一题【两数之和】开始刷&#xff0c;会让50%的人倒在起点。所以我们刷题要讲究路线攻略以及技巧~大体路线方向由简入难数学数组链表字符串哈希表双指针递归栈队列树图与回溯算法贪心动态规划刷题技巧 建议刷题的时候分…

Windows 电脑发现老是自动访问外网的域名排障步骤

Windows 电脑发现老是自动访问外网的域名,如何排障 一、基础信息获取与进程定位 1.1、确认进程关键信息 1.2、进程合法性初步验证 二、网络连接深度分析 2.1、目的IP/域名溯源 2.2、端口与协议检查 三、进程行为与系统异常排查 3.1、进程启动与依赖分析 3.2、系统异常行为扫描…

curl、python-requests、postman和jmeter的对应关系

一、初识curlcurl 是一个功能强大的命令行工具&#xff0c;用于传输数据&#xff0c;支持多种协议&#xff08;如 HTTP、HTTPS、FTP 等&#xff09;。分析以下curl&#xff1a;curl "https://$HOST/mon/adm/au/opera" --header "Authorization: $AUTH" -X …

【MySQL】初识数据库基础

【MySQL】初识数据库基础 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;MySQL笔记 文章目录【MySQL】初识数据库基础前言一. 数据库基础&#xff08;重点&#xff09;1.1 什么是数据库1.2 主流数据库1.3 基本使用1.3.1 MySQL安装1.3.2 连接…

微服务Docker-compose之若依部署

目录 1.创建一个文件夹 2.上传压缩包 3.解压 4.执行ry1文件 5.执行ry2文件 6.进入nginx的html目录解压dist文件 7.执行ry3文件 8.访问nacos 9.访问若依 1.创建一个文件夹 2.上传压缩包 3.解压 4.执行ry1文件 5.执行ry2文件 6.进入nginx的html目录解压dist文件 7.执行ry…