跳到主要内容

利用油猴脚本显示扇贝网真实打卡日记

· 阅读需 4 分钟

前一段时间发现扇贝网页版显示的打卡日记和手机上看到的不一致,感觉应该是网页版开发滞后的原因。这种不一致给查卡带来了诸多不便,于是就设法解决该问题。

起初我想到的方案是做一个静态页面放到对象存储上,然后对象存储开启静态服务,静态页面通过Ajax请求手机版的RESTful接口获取数据,然后生成打卡日记。不过,通过反复试验发现这种方法行不通。

$.get(url, function(data){
// do something
});

直接使用Ajax请求会报错:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是因为服务器不允许跨站。

然后接触到了用JSONP来进行跨站请求。因为js脚本可以跨站,像静态博客的评论功能就是用的跨站js脚本,JSONP的思路是在请求的地址上携带一个callback参数,服务端以这个callback参数作为函数名包裹JSON数据,然后在返回数据时调用这个函数,就把JSON数据传过来了。

$.ajax({
url: url,
dataType: 'jsonp',
success: function(json){
// do something
}
});

但是,使用JSONP的前提同样是需要服务器端的配合。假如服务器端不适配JSONP,也就是不返回包裹JSON数据的函数,而是依旧返回JSON,那么JSON数据就会被视为javascript脚本运行,会报错:

Uncaught SyntaxError: Unexpected token :

然后想到iframe也可以跨站,于是试试iframe,结果发现依然是想多了:

Refused to display '***' in a frame because it set 'X-Frame-Options' to 'deny'.

也就是iframe也是需要服务器端配合。假如服务器端不允许iframe,那么iframe便不能跨站。

跨站请求其实也比较危险,例如XSS、CSRF。于是,我决定不通过跨站请求,而是利用油猴脚本来实现我的需求,顺便补充了点jQuery。

// ==UserScript==
// @name 显示真实打卡日记
// @namespace https://www.shanbay.com/
// @version 0.1
// @description 显示时区、真实打卡日记、打卡时间
// @author 文剑木然
// @match https://www.shanbay.com/checkin/user/*
// @grant MIT
// @require https://static.baydn.com/static/scripts/jquery-1.7.2.min.js
// ==/UserScript==

$(function(){
var url = window.location.href
.replace('www.shanbay.com', 'www.shanbay.com/api/v1')
.replace('?page', '?ipp=10&page');
$.get(url, function(json){
// 显示时区
var timezone = json.data[0].user.timezone;
if(json.data.length > 0 && timezone !== 'Asia/Shanghai'){
$('h2').html($('h2').html() + '(' + timezone +')');
}
// 修改打卡日记
for(var i=0; i<10; i++){
var idata = json.data[i];
var icheckin = $('#checkin').children().eq(i);
var number = icheckin.find('span.number');
number.html(' ' + idata.num_checkin_days);
var note = icheckin.find('div.note');
if(json.data[i].note_length === 0){
note.html(idata.info);
}else{
note.html(idata.info + ' , ' + idata.note);
}
var date = icheckin.find('div.span4');
date.html('<strong>' + idata.checkin_date +
'</strong>&nbsp;&nbsp;&nbsp;&nbsp;(' +
idata.checkin_time.replace('T', '&nbsp;&nbsp;') + ')');
}
});
});

jQuery中,children()指直接子元素,.find()能递归查找子元素,.eq(i)为第i个元素。用jQuery来修改DOM还是十分简便的。