【油猴脚本】GM_xmlhttpRequest跨域请求初探

缘起

公司叫我们去考金蝶,并要求认证。金蝶官网提供了一些试题,基本上每个视频学习完成后就有对应的试题测验一下。
观察后发现,金蝶的网页做得还是很有规律的,试题与视频都是一一对应的:
视频页面(教学视频):
http://cplatform.kingdee.com/templates/course/course_details.html?courseId=677
测验页面(与视频对应的试题):
http://cplatform.kingdee.com/templates/course/exam_formal.html?courseId=677
于是在查看这些试题的时候想把题目上传到自己的数据库里,再做个随机抽题的页面,不就可以很方便地自己刷题了吗?
说干就干——

试题抓取

这里,我们在浏览测验页面时使用油猴(tamperMonkey)自动运行js脚本。由于这不是本文的重点,直接上代码:

//形如http://cplatform.kingdee.com/templates/course/exam_formal.html?courseId=677的测验页
    if(location.href.indexOf('exam_formal')>-1){
        let reg2 = /,/g
        let preCount =0, count = 0;
        const id = location.href.match(reg)[1];
        $.get('http://cplatform.kingdee.com/queryQuestionByCourseId?id=' + id, function(res){
            if(res.rows){
                for(let i = 0; i < res.rows.length; i++) {
                    let myAnswer = '';
                    let myOptions =[];
                    const options = res.rows[i].optionList;
                    let answer = '';
                    for (let j = 0; j < options.length; j++) {
                        myOptions.push(options[j].content.replace(reg2, ','));
                        myAnswer += (options[j].isQuestionAnswer === 1) ? ((answer ? ',' : '') + String.fromCharCode(65 + j)) : '';
                    }
                    GM_xmlhttpRequest({
                        method: "post",
                        url: 'http://192.168.0.109:8080/subject',
                        data: 'typeName=【' + id + '】' + res.data.title + '&content=' +res.rows[i].title + '&answer='+myAnswer+'&options=' +JSON.stringify(myOptions),
                        headers:  {
                            "Content-Type": "application/x-www-form-urlencoded"
                        },
                        onload: function(res){
                            if(res.status === 200){
                                console.log('成功')
                            }else{
                                console.log('失败')
                                console.log(res)
                            }
                        },
                        onerror : function(err){
                            console.log('error')
                            console.log(err)
                        }
                    });
                }
        // 用于在页面上显示参考答案
        $('.col-xs-12').bind('DOMSubtreeModified', function(e){
            count++;
            setTimeout(function(){
                if(preCount !== count){
                    preCount = count;
                }else{
                    $('.col-xs-12').unbind('DOMSubtreeModified');
                    $('.look_answer_exam').show();
                }
            },100);
        });
    }

首先,利用金蝶的api获取题目及答案

$.get('http://cplatform.kingdee.com/queryQuestionByCourseId?id=' + id)

这里的id就是http://cplatform.kingdee.com/templates/course/exam_formal.html?courseId=677中的677
请求得到的数据(在chrome的开发者工具中查看)如下:
试题数据
红框中的是题目提供的几个选项,如果该选项的isQuestionAnswer为1则表示该项是正确答案,content为选项的正文。

问题

金蝶的域名为 http://cplatform.kingdee.com
而我自己要上传数据的接口域名为 http://192.168.0.109:8080
显然,若使用ajax请求数据时会因跨域操作而被禁止。

$.ajax({
                        method: "post",
                        url: 'http://192.168.0.109:8080/subject',
                        ...
                        onload: function(res){
                            if(res.status === 200){
                                console.log('成功')
                            }else{
                                console.log('失败')
                                console.log(res)
                            }
                        },
                        onerror : function(err){
                            console.log('error')
                            console.log(err)
                        }
                    });
                })

跨域导致的请求失败
数据在上传到自己的服务器之前就被拦截了。
为了快点解决问题,直接使用tamperMonkeyGM_xmlhttpRequest

GM_xmlhttpRequest用法

设置

在js脚本顶部添加以下代码以允许跨域并启用GM_xmlhttpRequest

// @grant        GM_xmlhttpRequest
// @connect      *

“@connect *”表示允许任何域名的跨域请求。当然,我们这里写成“@connect 192.168.0.109”也是可以的,注意不需要加http://1
关于data的用法,最初我参考了tamperMonkey的文档2
由于文档并未详细说明data的格式于是想当然地认为和$.ajax一样,代码如下:

GM_xmlhttpRequest({
    method: "post",
    url: 'http://192.168.0.109:8080/subject',
    data: {
     	typeName: 'somthing',
     	content: 'somthing',
     	options: 'somthing'
	},
	onload: function(res){
		// code
	}
});

最后折腾了一个下午,发现Greasemonkey的文档3才有正确的说明。当然,Greasemonkey用的是GM.xmlHttpRequest,Tampermonkey用的是GM_xmlhttpRequest,故代码如下:

GM_xmlhttpRequest({
    method: "post",
    url: 'http://192.168.0.109:8080/subject',
    data: 'typeName=XXX&content=XXX&options=XXX',
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    onload: function(r) {
    	// code
    }
});

即,将Object类型的data用字符串拼成一个字符串即可。


  1. 可参阅:tamperMonkey官方文档 - @connect ↩︎

  2. 见此处: tamperMonkey官方文档 - @GM_xmlhttpRequest ↩︎

  3. 见此处: Greasemonkey的请求示例 ↩︎

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值