资讯专栏INFORMATION COLUMN

知乎快捷取消我关注的问题chrome插件

PAMPANG / 448人阅读

摘要:起因昨天上知乎一看,发现自己关注的问题接近个了,不能忍,希望控制在个以以内最好是个以内。到问题详情页分析取消关注的格式,使用问题拼装。功能说明把所有关注的问题列出来。而实际上知乎显示我关注的问题有个。知乎的列表的结构和接口都可能会修改。

起因

昨天上知乎一看,发现自己关注的问题接近1000个了,不能忍,希望控制在500个以以内最好是100个以内。于是打开我关注的问题列表。发现这个列表已经由滚动加载变成了分页,并且不能在问题列表页面直接点取消关注,需要进入问题详情页面去取消关注。这样一来工作量就太大了。
之前滚动加载的时候只要写个小脚本在控制台运行一下就可以把所有的问题加载出来,现在想把所有的问题加载出来就不行了。

但是作为一个前端,对页面上的东西,总是可以想想办法的。那就写个小小的chrome插件吧。

要实现的功能点:

一次性把所有的问题加载出来。

就在问题列表页面取消关注。

一次性加载所有问题

思路:

从第一页开始,依次模拟点下一页的按钮。每次点之前把当前页的问题列表的数据保存成html字符串。放进一个数组。

没有下一页按钮的时候,表示已经到了最后一页。拼装所有的html字符串。替换最后一页的列表区。

实现的时候要注意的是什么时候去点击下一页,在什么时机触发。因为我们要确定下一页的数据加载过来了,才能进行下一次点击,不然就可能出现漏页的情况。 观察页面发现每一页的数据加载好,知乎就会把滚动条移动到顶部去。所以我们可以通过监测scroll事件来判断当前页面的数据是否已经加载完毕。监测到scroll事件的时候就是我们发起下一次点击的时候。并且当下一页加载好之后我们要再把滚动条移动到底部去。这样加载新一页的时候滚动条才会再次往上移,从而触发我们绑定的scroll事件。
另外,就是scroll事件一般会一次性触发好多个。我们要保证我们绑定的事件的逻辑代码只执行一次。所以我加了一个timeout定时器,稍微延迟一下。等滚动条停下来的时候才真正执行事件逻辑。在这个timeout运行之前的再次触发的scroll事件都会直接return掉。并且设置一个适当延迟,也减小了被误认为是爬虫的概率。

就在问题列表页面取消关注

思路:

给每个问题加按钮。直接append就行了。并绑定事件。

从问题的dom结构中拿到问题的url,并从url中解析出问题id。

到问题详情页分析取消关注的url格式,使用问题id拼装。

自己发ajax请求。delete格式。

实现

为了方便,我就直接写成chrome插件使用了。就不用每次手动到控制台去运行了。
直接拿之前写的一个chrome插件的架子过来开干。
chrome插件的入门写法以及使用我之前有篇文章写过。一个简单的chrome拓展程序开发
并且之前的chrome插件架子里集成了jQuery,代码写起来就更欢快了。

/* 
 * 功能说明:
 * 1.把所有关注的问题列出来。
 * 2.给所有的问题添加取消关注按钮并完成取消关注。
 * 
 * author: liusaint@gmail.com
 * date: 20180120
 */

var ZhiHu = {
    htmlArr: [], //保存每一页的问题的html数据。
    pageItems: {}, //保存每一页的数量。
    INTEVAL: 2000, //翻页的时间间隔。请求下一页的间隔。可以调小一些。
    timer: "", //定时器
    //初始化。
    init: function() {

        var that = this;

        //绑定滚动事件。当页面滚动了就可以开始请求下一页的数据了。
        $(window).on("scroll", this.scrollFn.bind(this));
        //初始调用。
        this.scrollFn();

        //给我们添加的按钮绑定事件。
        $("body").on("click", ".del-q", function(event) {
            that.delQ($(this));
        });
    },
    //取消关注。拼装url,发送delete请求。
    //需要拼装的url接口格式:https://www.zhihu.com/api/v4/questions/20008370/followers
    delQ: function(jqObj) {     

        var questionUrl, matchArr, delUrl, questionId;

        //问题页面链接
        questionUrl = jqObj.siblings(".QuestionItem-title").find("a").attr("href");
        if (!questionUrl) {
            return;
        }

        //正则匹配问题id
        matchArr = questionUrl.match(/d+/);
        if (matchArr) {
            questionId = matchArr[0];
        }

        delUrl = "https://www.zhihu.com/api/v4/questions/" + questionId + "/followers";

        $.ajax({
            url: delUrl,
            type: "delete",
            success: function(data) {
                //成功的话删除该列。
                jqObj.closest(".List-item").remove();
            }
        })

    },
    //页面滚动时触发的事件。
    scrollFn: function(event) {
        var that = this;
        //滚动条滚动时会多次调用此方法,拦截掉。
        if (this.timer) {
            return;
        }
        this.timer = setTimeout(function() {
            //页面内容提取
            that.saveData();

            //如果有下一页,模拟点击。
            if ($(".PaginationButton-next").length > 0) {
                $(".PaginationButton-next")[0].click();
                //移动到底部。
                that.scrollBottom();
            } else {
                //到了最后一页了。最后的数据处理。
                that.mergeList();
                //解绑事件
                $(window).off("scroll");
            }

            clearTimeout(that.timer);
            that.timer = "";
        }, this.INTEVAL)

    },
    //从页面中提取问题html数据与每页的数量。
    saveData: function() {
        var html = $(".List-header+div").prop("outerHTML");
        this.htmlArr.push(html);
        //当前页面的问题数量
        this.pageItems[$(".PaginationButton--current").text()] = $(".List-item").length;
    },
    //数据收集完成后对列表的处理。
    mergeList: function() {
        var html = this.htmlArr.join("");
        //组装所有页的数据到一页。
        $(".List-header+div").html(html);
        //移除分页
        $(".Pagination").remove();
        //给每个问题添加取消关注按钮
        $(".ContentItem-title").append("");
        //把每页的数量打出来看一下,发现并不是每页都是20条数据。
        top.console.log(this.pageItems);
    },
    //滚动到底部
    scrollBottom: function() {
        var h = $(document).height() - $(window).height();
        $(document).scrollTop(h);
    },

}

/* chrome插件部分。核心代码是上面的内容 */
chrome.extension.onRequest.addListener(
    function(request, sender, sendResponse) {
        if (request.greeting == "hello") {
            //执行上面的内容
            ZhiHu.init();
        }
    }
);
问题

插件完成,加载到chrome浏览器,点击运行。功能正常。大功告成。

不过当所有问题都加载出来之后发现了比较奇怪的事情,就是一共加载出来911个问题。而实际上知乎显示我关注的问题有950个。所以我一度怀疑是不是哪个逻辑有错误少加载了一两页的数据。就在代码里加入了一个对象保存每一个问题页面的问题数据。
得出的结果是并不是每一页都有20个问题的。有些页面只有19个,最少的甚至只有16个。于是我点开某一页最少的,挨个数一下,发现真是只有16个。然后把这些数据加起来,确实是911个。
另外39个问题真是消失在搜索结果中了。

补充

本代码具有时效性,仅供参考。知乎的列表的dom结构和接口都可能会修改。如果发现代码不能运行,可以酌情修改代码再运行。

效果图:

插件github地址

文章github地址

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92636.html

相关文章

  • 可以提高程序员效率工具!

    摘要:首先去装个替代原生的终端,多种主题配色,这里我的主题用的是随后,去下一个替代原生的,可以看一下我弄好以后的配色关键字高亮自动提示命令最后本文涉及的所有软件和下载地址破解码,安装教程在公众号下回复工具即可全部获取乐于输出干货的技术公众号。 前言 只有光头才能变强。文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 本...

    lemon 评论0 收藏0
  • 前端资源系列(4)-前端学习资源分享&前端面试资源汇总

    摘要:特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 本以为自己收藏的站点多,可以很快搞定,没想到一入汇总深似海。还有很多不足&遗漏的地方,欢迎补充。有错误的地方,还请斧正... 托管: welcome to git,欢迎交流,感谢star 有好友反应和斧正,会及时更新,平时业务工作时也会不定期更...

    princekin 评论0 收藏0
  • ZhihuVAPI:用Python优雅地玩知乎

    摘要:优雅地玩知乎简介是什么是一个可以让你以一种优雅的形式调用知乎数据的包怎么安装或者更新使用引用后面的是别称的意思便于输入配置用户配置脚本使用的一共有两种方法什么都不管脚本会默认读取或者的如果你是其他类的浏览器你可以在的自定义文件的路径在禁用 ZhihuVAPI:优雅地玩知乎 简介 ZhihuVAPI是什么? ZhihuVAPI 是一个可以让你以一种优雅的形式调用知乎数据的 Python ...

    ccj659 评论0 收藏0
  • 被「李笑来老师」拉黑之「JavaScript微博自动转发脚本」

    摘要:本以为花一两个小时就能搞定这个微博自动转发的脚本,结果中途不停的踩坑折腾了大半天。还好早早的被李笑来老师拉黑。填坑过程打开浏览器中,先登录自己的微博,再进入李笑来老师的微博首页。然后手动转发一次微博,获取到转发时所产生的请求。 故事的背景如下图,李笑来 老师于10月19日在 知乎Live 开设 一小时建立终生受用的阅读操作系统 的讲座,他老人家看到大家伙报名踊跃,便在微博上发起了一个 ...

    BaronZhang 评论0 收藏0

发表评论

0条评论

PAMPANG

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<