FBI WARNING
上节课在实战的时候我发现存在严重错误,根据cxxjackie的提示和帮助下进一步完善了代码,相对来说还是较重的,下节课会介绍另一种方法。
上节课的主要错误在于,部分网页对于fetch存在一个喜欢写入自定义数据和读入自定义数据的问题。
由于我创建了一层多余的空对象,网页过掉了porxy,直接在空对象写入数据,导致出现错误。
以下代码仅经过了少量的测试,不代表真的不存在问题,如果存在问题可以反馈给我。
let oldfetch=fetch
function newobj(){}
function fuckfetch(...bianliang){
return new Promise(function(resolve, reject){
oldfetch(...bianliang).then(function(response) {
let handler = {
get: function(target, prop, receiver) {
if(typeof Reflect.get(target,prop)==='function')
{
if(Reflect.get(target,prop+'proxy')===undefined)
{
target[prop+'proxy']=(...funcargs)=> {
let result=target[prop].call(target,...funcargs)
//书写劫持的函数代码
console.log('fetchfunction',bianliang,prop,funcargs,result)
return result
}
}
return Reflect.get(target,prop+'proxy')
}
return Reflect.get(target, prop);
},
set(target, prop, value) {
return Reflect.set(target, prop, value);
},
};
let proxy=new Proxy(response, handler)
resolve(proxy)
})
});
}
window.fetch=fuckfetch
然后我们通过抓包可以看到
https://www.zhihu.com/api/v3/feed/topstory/recommend?
是获取刷新列表的fetch api
运行脚本,可以发现这个api调用的json进行的返回对象的json化,所有我们开写代码了!
首先判断变量的长度,以及url,如果都没问题,再判断调用的函数名是否是json,如果满足的话
说明我们需要进行劫持了!
观察result返回的内容,json返回的是一个Promise
所以我们也需要返回一个Promise
if(bianliang.length!==0&&bianliang[0].indexOf('/api/v3/feed/topstory/recommend')!==-1&&prop==='json'){
return new Promise(function(resolve, reject){})
}
我们在promise内先获取result的结果,然后进行处理,再resolve结束我们创建的这个promise
所以这里的完整代码就是
if(bianliang.length!==0&&bianliang[0].indexOf('/api/v3/feed/topstory/recommend')!==-1&&prop==='json'){
return new Promise(function(resolve, reject){
result.then(
function(data){
console.log('bianliang',bianliang)
let retobj={
data:[],
fresh_text:data.fresh_text,
paging:data.paging,
}
for(let index=0;index<data.data.length;index++){
if(data.data[index].ad===undefined){
retobj.data.push(data.data[index])
}
}
resolve(retobj)
}
)
})
}
我在result.then上挂载了一个函数,并执行相应的处理,最后在resolve回去数据,
返回的数据创建了三个属性,fresh_text以及paging都原封不动的传递,data,需要我们进行处理,这里我们可以使用ES6特性解包直接完成,但是代码相对更骚一点,很多人看不懂,暂时先忽略掉。
紧接着对result返回的data数据的data属性做一个便利,如果不存在ad属性就push进retobj的data数组上。
那目前为止我们已经解决大部分问题了,最后还有一个问题就是页面最初载入的时候也有一个广告,我们应该如何处理呢?
这里由于不属于教程返回,就简单粗暴处理了一下。
window.onload=function(){
document.querySelector('.Pc-feedAd-container').parentElement.style.display='none'
}
具体脚本可以参考
https://bbs.tampermonkey.net.cn/forum.php?mod=viewthread&tid=911
结语
感谢cxxjackie对于fetch部分的帮助
撒花~