获取iframe中元素,提示跨域访问出错
站内王一之大佬写的解决跨域问题的两个方法,都看了,不知道具体怎么才能解决在iframe的页面上执行脚本,并返回页码数,目前的想法是设置全局变量n,在iframe界面运行脚本,改变变量n[基本油猴编程的一些常见误区](https://bbs.tampermonkey.net.cn/thread-835-1-1.html)
stackOverflow上有个相关回答,采用postMessage()进行跨域通信,实在搞不动怎么用到我这个脚本
(https://stackoverflow.com/questions/25098021/securityerror-blocked-a-frame-with-origin-from-accessing-a-cross-origin-frame)
针对全国招投标公告打印不全,写了一个脚本,PDF的页数的ID = ‘numPages’,用document.getElementById('numPages')定位或者document.querySelector('#numpages'),元素都获取不到,提示Blocked a frame with origin from accessing a cross-origin frame,
目前采用的是弹窗输入,解决页数的问题。但是发现很多页面都是有iframe,所以想搞清楚到底要怎样才能自由的获取iframe中的元素
下面是需要脚本运行的示例界面
`https://ctbpsp.com/#/bulletinDetail?uuid=0f54093b-3869-4611-b2b5-71fd465e2670&inpvalue=2022%E5%B9%B4%E6%B9%96%E5%8D%97%E4%B8%AD%E7%83%9F%E7%A7%91%E7%A0%94%E8%AE%BE%E5%A4%87&dataSource=1`
```// ==UserScript==
// @name 调整打印文件
// @namespace print adjust
// @match https://ctbpsp.com/#/bulletinDetail?uuid=*
// @match https://bulletin.cebpubservice.com/qualifyBulletin/*
// @match https://bulletin.cebpubservice.com/biddingBulletin/*
// @match https://bulletin.cebpubservice.com/candidateBulletin/*
// @match https://bulletin.cebpubservice.com/resultBulletin/*
// @run-at document-end
// @grant unsafeWindow
// @version 1.2.2
// @author 我爱小熊啊
// @description cebpubservice.com 文件加载时间较长,遇到未加载完成的,页码输入界面点击取消,文件加载完后,记住页码,刷新输入页码,等待加载完成
// @description 将 ctbpsp.com 与 cebpubservice.com 的等待时间做区分
// @description 自动隐藏 cebpubservice.com 上的二维码广告
// @description 增加对 cebpubservice.com的支持
// @description 中国招标投标公共服务平台公告文件打印调整
// @description 2022/8/3 08:33:33
// @license MIT
// ==/UserScript==
// 设置延时定时器,避免网页未加载完,弹出页码输入框
setTimeout(function(){
var weburl = window.location.href;
var n = 1;
// ctbpsp.com 网页打印
if(weburl.indexOf('ctbpsp.com')!=-1){
// var windowAttribute = $('iframe');??? 引入 jQuery 库也不生效
var windowAttribute = document.getElementsByTagName('iframe');
n = prompt('请输入文件页码','');
if(n){ // 如果输入框点击取消,则 prompt 返回的是 null,则取消更改,否则网页会出错
windowAttribute.width = 900;
windowAttribute.height = 1150 * n;
// alert("Hello");
}
}
// cebpubservice.com 网页打印
if(weburl.indexOf('cebpubservice.com')!=-1){
setTimeout(function(){
var p = document.getElementsByClassName('pdf_wraper');
var b = document.getElementsByClassName('PublicAddress');
b.style.display = 'none';
// var n = prompt('请输入文件页码','');
n = prompt('请输入文件页码','');
if(n){
p.style.width = '900px';
var h = n * 1150;
var gaodu = h + 'px';
p.style.height = gaodu;
}
}, 6000);
}
}, 3000);
``` iframe内部可以理解为另一个网页,如果网页跨域,那无论如何也是不能直接操作其中的元素的。跨域页面可以通过postMessage互相发送数据,根据数据在对应环境中执行对应操作,这需要双方的配合。比如A可以给B发送一个指令showMessage,B接收到以后展示相应元素,但A不能直接操作B内的元素。全局变量是没用的,代码虽然看起来在同一个脚本,但实际运行在不同的环境中。下面是实现你需求的一个示例:
// ==UserScript==
// @name 跨域交互
// @description...
// @namespace ...
// @author ...
// @version 1.0
// @match https://ctbpsp.com/*
// @match https://custominfo.cebpubservice.com/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// 主页面
if (location.hostname === 'ctbpsp.com') {
// 监听message事件,取得页码数后调整iframe大小
window.addEventListener('message', e => {
if ('numPages' in e.data) {
const iframe = document.querySelector('.pdf-viewer');
iframe.width = 900;
iframe.height = 1150 * e.data.numPages;
}
});
}
// iframe页面
if (location.hostname === 'custominfo.cebpubservice.com') {
// iframe内有一个全局对象PDFViewerApplication,可对其进行劫持来判断pdf加载完毕,也可以用其他方法。
const _load = window.PDFViewerApplication.load;
window.PDFViewerApplication.load = function(pdfDocument) {
// 获取页码数,发送给主页面
window.top.postMessage({
numPages: pdfDocument._pdfInfo.numPages
}, 'https://ctbpsp.com');
return _load.call(this, pdfDocument);
};
}
})(); 如有哪位大佬能帮我解决这个问题,悬赏20元人民币,QQ:1664307236 iframe子对父通信使用postmessage思路是对的
可以参考
https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=2267 还有一个思路就是使用
GM_addValueChangeListener
GM_removeValueChangeListener
GM_setValue
三个api组合
这还是一个关于iframe的异步获取元素的问题,我之前谈过waitForKeyElements这个库遇到的跨域问题,你和我遇到过的问题很像。
cxxjackie专门写了一个库ElementGetter来解决此类问题,我估计cxxjackie大佬看到后会来推广他的ElementGetter。
我先给出使用waitForKeyElements的方法,抛砖引玉。
1.头部没有匹配iframe的网址,需要匹配:
```js
// @match https://custominfo.cebpubservice.com/*
// @require https://z.chaoxing.com/js/jquery-3.5.0.min.js
// @require https://greasyfork.org/scripts/383527-wait-for-key-elements/code/Wait_for_key_elements.js?version=701631
// @grant none
```
2.使用waitForKeyElements获取numPages的代码:
```js
waitForKeyElements ("span#numPages.toolbarLabel",(jNode)=>{
console.log(jNode); //输出 <span id="numPages" class="toolbarLabel">/ 4</span>
console.log('fuck you')
},'iframe.pdf-viewer');
```
3.相关帖子
- [异步获取元素的脚本库 ElementGetter (更新至1.1.1)](https://bbs.tampermonkey.net.cn/thread-2726-1-1.html)
- [异步获取元素的脚本库waitForKeyElements](https://bbs.tampermonkey.net.cn/thread-2729-1-1.html)
朱焱伟 发表于 2022-8-9 19:50
这还是一个关于iframe的异步获取元素的问题,我之前谈过waitForKeyElements这个库遇到的跨域问题,你和 ...
这其实不是获取元素的问题,跨iframe≠跨域。waitForKeyElements只能获取同源iframe内的元素,ElementGetter也不能解决跨域。 本帖最后由 朱焱伟 于 2022-8-9 22:12 编辑
cxxjackie 发表于 2022-8-9 21:37
这其实不是获取元素的问题,跨iframe≠跨域。waitForKeyElements只能获取同源iframe内的元素,ElementGet ...
看到最新评论的代码了,老铁666 cxxjackie 发表于 2022-8-9 21:46
iframe内部可以理解为另一个网页,如果网页跨域,那无论如何也是不能直接操作其中的元素的。跨域页面可以通 ...
感谢大佬指点,作为一个小白,太感谢了,确实解决了我的困扰,之前悬赏的20元,看怎么给方便点,请大佬喝杯咖啡 李恒道 发表于 2022-8-9 19:44
还有一个思路就是使用
GM_addValueChangeListener
GM_removeValueChangeListener
感谢大佬回复,之前就是在论坛看你的帖子,写的第一个脚本,虽然很简单,但是对我而言,解决了工作中的一个问题,也是很有成就感了
页:
[1]
2