10

日常松果煲粥一键发现宝藏答主!!!

 3 years ago
source link: https://zhuanlan.zhihu.com/p/332801715
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

李国宝:想法抽奖不讲伍德,年轻人还是耗子喂汁啊

李国宝:手把手教你改一行代码爬取知乎热榜

李国宝:想法抽奖嘛,要什么自行车....

前几天松果@松果煲粥 这朋友说想要看下自己的关注者里面有什么宝藏答主,

我看了下感觉好像也还有点意思,

于是周末就折腾了一下怎么获取自己的关注者。

首先我们还是搞了下知乎API,发现最近他们开始搞签名了。

QZviIvA.jpg!mobile 签名。jpg

怎么说呢?

年轻人还是耗子尾汁。

明显我这么懒肯定不继续搞签名了,

松果又不给我煮粥...

不讲武德的。。。

直接脚本点页面嘛,不断下一页过去,总能把数据捞回来。

ma2qymA.jpg!mobile

直接上代码.

// 知乎关注者信息抓取脚本
// 打开自己的关注者列表页,手动翻到第一页
// 打开浏览器控制台
// 贴入下面的脚本,观察输出日志
// 抓取完成后自动生成csv文件弹出下载框


// 宝藏知友的被关注量
var minFollowerNum = 5000;

// 所有的关注者信息
var userFollowers = [];
// 待关注的知友
var waitingFollowers = [];
// 是否自动关注, 建议不要
var autoFollow = false;

var allPageButtons = document.getElementsByClassName("Button PaginationButton Button--plain");
var lastPageButton = allPageButtons[allPageButtons.length - 2];
if (!lastPageButton) {
    console.log("没有最后一页数据,直接退出。");
}

// 当前所有的关注者列表分页数量
var maxPageNum = Number(lastPageButton.textContent);
// 如果太多了,可以默认获取前60页的关注者数量,这里默认是60
// var maxPageNum = 60;

console.log("当前页面总页数:" + maxPageNum);
var pageIndex = 1;
var dt = setInterval(function () {
    var currentUsers = document.getElementsByClassName("List-item");
    for (var userIndex = 0; userIndex < currentUsers.length; userIndex++) {
        var userItem = currentUsers[userIndex];
        if (userItem.getElementsByClassName("Avatar Avatar--large UserLink-avatar")[0] == undefined
            || userItem.getElementsByClassName("UserLink-link")[0] == undefined) {
            continue;
        }
        var userInfo = convertToUserInfo(userItem);
        if (userInfo.followerNum && userInfo.followerNum >= minFollowerNum && userInfo.followStatus != "相互关注") {
            console.log("发现没有关注的知友【" + userInfo.userName + "】关注数【" + userInfo.followerNum + "】超过【" + minFollowerNum + "】,自动添加到宝藏知友列表。");
            waitingFollowers.push(userInfo);
        }
        userFollowers.push(userInfo);
    }
    var nextPageButton = document.getElementsByClassName("Button PaginationButton PaginationButton-next Button--plain")[0];
    console.log("正在获取第【" + pageIndex + "】页数据,当前关注者数量:" + userFollowers.length + ", 当前宝藏知友列表数量:" + waitingFollowers.length);
    // 下一页还存在 + pageIndex 小于最大的页码
    if (nextPageButton && pageIndex <= maxPageNum) {
        nextPageButton.click();
        pageIndex = pageIndex + 1;
    } else {
        clearInterval(dt);
        console.log("获取全部数据成功,当前数据总数:" + waitingFollowers.length);
        console.log("开始下载...");
        // 所有的关注者数据
        // downloadJSON2CSV(userFollowers);
        downloadJSON2CSV(waitingFollowers);
    }
}, 1000);


// 下载CSV
function downloadJSON2CSV(objArray, filename) {
    var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
    var csvText = '';
    for (var i = 0; i < array.length; i++) {
        var line = '';
        // for (var index in array[i]) {
        //     line += array[i][index] + ',';
        // }
        //添加双引号
        for (var index in array[i]) {
            line += '\"' + array[i][index] + '\",';
        }
        line.slice(0, line.Length - 1);
        csvText += line + '\r';
    }
    if (!filename) filename = "followers_" + new Date().valueOf() + '.csv'
    var blob = new Blob(
        [
            new Uint8Array([0xEF, 0xBB, 0xBF]), // UTF-8 BOM
            csvText
        ],
        { type: "text/plain;charset=utf-8" }
    );
    e = document.createEvent('MouseEvents');
    a = document.createElement('a');
    a.download = filename;
    a.href = window.URL.createObjectURL(blob);
    a.dataset.downloadurl = ['text/csv;charset=utf-8', a.download, a.href].join(':');
    e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e)
}

// 将页面的数据转换成Json对象
function convertToUserInfo(userItem) {
    var userInfo = {};
    userInfo.userName = userItem.getElementsByClassName("Avatar Avatar--large UserLink-avatar")[0]["alt"];
    userInfo.userURL = userItem.getElementsByClassName("UserLink-link")[0]["href"];
    userInfo.userIntro = userItem.getElementsByClassName("ztext")[0] && userItem.getElementsByClassName("ztext")[0].innerText;
    userInfo.followStatus = userItem.getElementsByClassName("FollowStatus")[0].innerText;
    var statusItems = userItem.getElementsByClassName("ContentItem-statusItem");
    if (statusItems.length > 0) {
        var lastItemText = statusItems[statusItems.length - 1].innerText;
        if (lastItemText.indexOf("关注") > 0) {
            userInfo.followerNum = Number(lastItemText.replace("关注者", "").replace(",", "").replace(" ", ""));
        }
    }
    return userInfo;
}

目的:遍历所有关注者,被关注数量大于阈值则添加到导出列表

食用方法:

一: 打开自己的关注者页面

调出浏览器开发者工具(一般是F12快捷键,建议使用谷歌Chrome浏览器,火狐)

6beq2qM.jpg!mobile

然后在“Console”里面贴入上面的代码,回车走起。

页面会自动跑起来,没问题的话日志输出如下:

yeaQ3qa.jpg!mobile

最后会自动弹出下载框,点击保存到本地。

uaaAfeQ.jpg!mobilezuyIvmB.jpg!mobile 表格文件

表格大概是这样的,

接下来的就自己决定啦。

PS:如果中途遇到什么奇怪的问题中断了,又没有跳出保存文件的话,可以手动输入

downloadJSON2CSV(waitingFollowers);

这样会把之前的结果保存到本地。

PPS: 中途中断的话,刷新一下当前页面,重新输入最上面的长代码,可以继续获取的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK