前言
这是一个阳光明媚的大早上,突然嗖的一下我的一个QQ消息来了,是我的一个初中同学,上来直接问我:
她:你是码农吗?
我:是?
她:到底是不是?
我:是吧!
她:是就好,我问你个东西,我的抖音账号里面莫名其面的有30多万的点赞视频,这个有什么办法快速取消掉吗?
我:有
我研究中......
元婴期
我想了想 怎么写,经过几分钟的思考,我决定用油猴脚本试一下,就是在网页版模仿人点击按钮下滑视频,然后在点击取消点赞!是不是很聪明,哈哈!不能这样说,是我自恋了,你们息怒息怒!
代码如下,请大佬们审阅:
(function () {
'use strict';
// Your code here...
let flag = false;
let m, n;
let ht;
let timer = null
let html = []
html.push(`<div id='newwbbie' draggable="true" style='right: 5px;top: 5px;background: #eee;z-index: 9999;position: fixed;border-radius: 4px;padding: 10px;box-shadow: 0px 0px 10px 5px rgb(25 25 25 / 20%);'>`)
html.push(`<button type='button' id='b0'>下滑删除</button>`)
html.push(`<button type='button' id='b1'>上滑删除</button>`)
html.push(`<button type='button' id='b2'>下滑红心</button>`)
html.push(`<button type='button' id='b3'>上滑红心</button>`)
html.push(`<button type='button' id='b4'>停止</button>`)
html.push(`<button type='button' id='b5'>开启刷新</button>`)
html.push(`<button type='button' id='b6'>停止刷新</button>`)
html.push(`</div>`)
$("body").append(html.join(''));
// 由于篇幅字数限制,只能省略...
async function fun(type) {
timer = setInterval(() => {
var parentElement = document.querySelector('[data-e2e="feed-active-video"]');
if (parentElement) {
// 通过父元素选择比较深的子元素
var prev_btn = parentElement.querySelector('[data-e2e="video-switch-prev-arrow"]');
var next_btn = parentElement.querySelector('[data-e2e="video-switch-next-arrow"]');
var digg_btn = parentElement.querySelector('[data-e2e="video-player-digg"]');
digg_btn.click()
if (type == 'prev') {
prev_btn.click()
}
if (type == 'next') {
next_btn.click()
}
}
}, 1000);
}
})();
经过一个小时的努力,惊奇的发现既然才取消了666个视频,愤怒的我一拍大腿,去求吧!这怎么能忍,这要是能忍,屎都能吃!
化神期
经历过拍过大腿又加上吃屎的经历后,经历了3分钟的思考后,我看了一下控制台,突然灵魂出窍,看到了页面DOM里面有每个视频的id,于是就做了一个神乎其技的灵魂对话:
我:为什么不能从页面DOM获取视频id,然后调用取消接口取消呢?
灵魂:你傻逼!
我:操
灵魂:你再说一句?小心我走!
我:好好好,哥,别走,你走我就挂了
于是经过10几分钟的修炼,我写出了下面的代码,看着代码我简直无法用中华文化来形容自己,只能说一句:卧槽,真是太厉害了!
代码如下、代码如下、代码如下,大佬们请审阅:
(function () { 'use strict'; // Your code here... let flag = false; let m, n; let ht; let ids = []; let html = [] html.push(`<div id='newwbbie' draggable="true" style='right: 95px;top: 5px;background: #eee;z-index: 9999;position: fixed;border-radius: 4px;padding: 10px;box-shadow: 0px 0px 10px 5px rgb(25 25 25 / 20%);'>`) html.push(`<div style='display:flex;'>当前页面视频数:<div id='t0'>0</div></div>`) html.push(`<button type='button' id='b2'>开启5s刷新</button>`) html.push(`<button type='button' id='btn60'>开启60s刷新</button>`) html.push(`<button type='button' id='btn300'>开启300s刷新</button>`) html.push(`<button type='button' id='b6'>停止刷新</button>`) html.push(`<button type='button' id='b8'>点红心</button>`) html.push(`<button type='button' id='b9'>消红心</button>`) html.push(`<button type='button' id='allRemove'>批量40消红心</button>`) html.push(`</div>`) $("body").append(html.join(''));
// 由于篇幅字数限制,只能省略... function allRemoveLike(ids) { // 批量取消代码省略.... } function removeLike(cur) { // 单个取消代码省略.... } async function fun() { flag = true; while (flag) { let divList = document.getElementsByTagName('div'); for (let d of divList) { if (d.getAttributeNames().includes('data-e2e-state')) { if (m == 1) { // 取消红心 if (d.getAttribute('data-e2e-state') == 'video-player-is-digged') { d.click() await sleep(0) break } } else { if (d.getAttribute('data-e2e-state') == 'video-player-no-digged') { d.click() await sleep(0) break } } } } // 滚动 for (let d of divList) { if (d.getAttributeNames().includes('data-e2e')) { if (n !== 2) { // 只向下滚动 if (d.getAttribute('data-e2e') === 'video-switch-next-arrow') { d.scrollIntoView(false); // 向下滚动 break; } } } } await sleep(0); } } function stop() { flag = false; } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }})();
化神中期
经过验证,发现这样的方式到最后会造成浏览器非常卡顿,还会造成浏览器崩溃,一恼火又拍了几下大腿,服了!这不是低级错误吗,加载一万多个视频元素,浏览器能不卡吗,谁家浏览器能无限制这样搞!于是我跟我的灵魂又陷入了沉思!哎!
突然灵魂发起拷问:
灵魂:你为什么不调用接口来获取?
我:也对哦!你真能!全村数你最能!
灵魂:别扯犊子,你初中同学等不及了!
我:哦!
于是经历了艰难的化神后期........
合体期
后来我借阴阳之机、心光之焱、雷霆淬砺、乾坤作冶,此至今日,终于剑成!
代码就不公开了吧!
这个代码真的是神乎其技,但是呢,经过反复测试,有点小不足,大概获取数据到一两万条的时候会触发官方的封控,弹出验证码,这就很烦喽!比如说:有一个人让你帮她取消喜欢视频,难道你要一直盯着吗?这样就太累了,但是也没办法啊!作为一个小前端又不能把人家的验证码给pojie掉,这样不就要被查水表了吗,况且我也没那水平啊!
但是我不甘心,不甘心,我要想其他办法
又经历了艰难的合体期,我突然灵光一现,app好像没有验证码哦!那我为什么不抓一下app的包呢!说干就干,下载fidder抓包工具,下载模拟器,配置环境,开始抓包!不会的小伙伴可以看看这篇文章哦!blog.csdn.net/weixin_6233…
当你信心满满的吧抓包环境配置的非常完美,准备大干一场的时候. 发现某音apk用了SSLPinning
又当大家信心满满的把frider过SSLPinning 以及xposed的justtrustme安装到手机上的时候再次打开apk,发现某音apk用的竟然是非系统的的ssl库
呵呵呵呵呵呵呵呵.......
某音你真狗!
经过查阅资料发现有一种很牛逼的方法,就是使用xposed模块hook到ssl请求,然后强制走TCP协议,也就是所谓的降级操作!但是这说起来容易,又该怎么做呢,我就是个小前端啊!哎!难难难!难于上青天!
但是没办法啊,初中同学的请求,关键还是她...,艹,不会就学,写一个xposed的hook模块,不过从头开始写是不可能的,只能站在巨人的肩膀上修改,于是就在github找着了这个开源库justtrustme,改改改!!!!!
成神期
生了生了,不对不对,是成了成了.....
怎么配置模拟器抓包请看这个文章,zhuanlan.zhihu.com/p/581365638 但是这家伙没有给模块,私信了他一下还需要300块钱给模块,太气人了,收费就自己写!
经过抓包以后后面就好解决了,于是我就写了个nodejs的爬虫代码,成品效果如下:
经过一个小时的努力,她的视频终于被清理完了!
总结
纵使前方有再多困难,只要她想要,我就排除千万困难给她最好的一切!兄弟们加油!此篇文章仅供学习交流!