思寒的老文章,翻出来玩玩。@seveniruby

背景

看到以前有个安全行业的人搞了一个研究, 叫 安全圈就这么大, 大家可以自行 Google
我也心血来潮, 也想分析下, 就依葫芦画瓢也做个研究.

初步的想法是, 先挑选一批牛人, 抓取牛人的 fans,
如果一个人是测试行业的人, 他应该会至少关注名单中的 2 个以上的测试人物.
然后就可以找到一批圈内的工程师做分析了.

准备

挑选了一批牛人, 我没有进行广度的遍历抓取, 我怕圈子太大, 会爬一星期都不完整. 就先从一些名人列表中进行数据汇总. 名单如下

Monkey陳曄曄
Oscar_Xie
芈峮
蔡为东
熊志男
施懿民
Philonis高
晋恒温
浪头
段念
朱少民
蔡为东
土司阿哈
吴穹adam
冬魁_kevin
百度质量部
柴阿峰
架构师Jack
季哥_岁月无声
xingzunxi
DiggerPlus
公公直直V
阿里窥基
钟柱
阿里技术质量部
槽神刘叫兽
贺炘

本来打算使用新浪 api, 后来发现新浪从上一年开始已经限制了 api 中 fans 的抓取, 需要高级认证才行, 审核需要一星期. 也等不及, 所以就先使用网页抓取的方法去获得数据.
新浪在网页上有个限制, 只能读取每个人前十页的 fans. 结果很少, 差不多 200 不到, 我抓取了 20 人左右, 漏掉的部分 fans 也可以在其他地方也可能会弥补下, 所以就先将就了.
先找到目前圈内的部分工程师再说, 后期再认证新浪开发者, 拿到全部的数据.

执行过程

首先编写了一个 selenium 的自动化程序, 爬取新浪的网页, 抽取数据.
填写上一些测试名人的名单. 分别打开每个人的 fans 页面, 抽取前十页的 fans.
并把关系输出出来.

分析过程

然后把数据结果保存为 csv 格式, 通过 cytoscape 图分析软件做分析, 结果如下
首先分析所有的数据

这是我挑选的二十多位名人的 fans 图, 可以看出来大家的 fans 重合度如何

使用 circle 图分析谁是圈内人, 谁是圈外人

圈外人一般是亲朋好友, 圈内人才是关注行业发展的优秀人才. 所以继续分析圈内同学

下面是挑选的名人名单中的 fans 关注程度.
当然不太准, 因为爬取的 fans 数量有限, 所以仅供参考, 如果拿到全部的数据, 这个图就会更权威.

最后上一个关注名单中名人三个以上的所有同学的全家福. 因为论坛对图片做了处理, 导致清晰度下降.
我把高清大图也放到了 qq 群里面了. 大家可以看看有么有自己..

结论

因为数据是不完整的, 所以就暂不给结论了.
期待有感兴趣同学, 可以搞出来完整版本的数据分析.
或者其他诸如
移动测试圈有多大
测试 QQ 群有多大
之类的更详细的分析数据.

我另外也爬取了各个大牛自己关注的人物, 用来分析大牛们有多"志同道合", 数据因为新浪的限制导致也是不完整的, 我就不公开了, 大家可以考虑结合下

不足之处

  1. 新浪的 api 需要开发者认证, 我暂时只能通过网页爬取.所以 fans 数据不全.
  2. 自己定制了名单, 应该是根据某个人物的关注列表继续深度爬取. 因为担心数据太大, 半天跑不完, 所以就没做.
  3. 可以考虑加入更多数据分析, 比如所在公司, 简介, 地点等.
  4. 没时间 后续也不会研究了, 只能期待看其他同学的分析结果了.

代码参考

因为是临时验证, 所以写的有点挫. 我也是刚开始用 Java. 只是练手, 名单图省事都直接硬编码进去了, 仅供参考

public class Weibo {

    @Test
    public void test() throws MalformedURLException, InterruptedException {
        System.setProperty("webdriver.chrome.driver",
                "C:\\Windows\\System32\\chromedriver.exe");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("user-data-dir=C:\\Users\\thinkpad\\AppData\\Local\\Google\\Chrome\\User Data");
        WebDriver driver = new ChromeDriver(options);

        Hashtable<String, String> table = new Hashtable<String, String>();
        table.put("Monkey陳曄曄", "1005051881320895");
        table.put("Oscar_Xie", "1005051863082301");
        table.put("芈峮", "1005052644045772");
        table.put("蔡为东", "1005052090356343");
        table.put("熊志男", "1005051139370681");
        table.put("施懿民", "1005052128792480");
        table.put("Philonis高", "1005051708094104");
        table.put("晋恒温", "1005051825985157");
        table.put("浪头", "1005051650836952");
        table.put("段念", "1005051859409827");
        table.put("朱少民", "1005051652927771");
        table.put("蔡为东", "1005052090356343");
        table.put("土司阿哈", "1005051846383733");
        table.put("吴穹adam", "1005051880082254");
        table.put("冬魁_kevin", "1005051913632955");
        table.put("百度质量部", "1006061829382261");
        table.put("柴阿峰", "1005051586920031");
        table.put("架构师Jack", "1005051930154725");
        table.put("季哥_岁月无声", "1005051828197054");
        table.put("xingzunxi", "1005051870376581");
        table.put("DiggerPlus", "1005051893906792");
        table.put("公公直直V", "1005051780334190");
        table.put("阿里窥基", "1005052607195824");
        table.put("钟柱", "1005051679085224");
        table.put("阿里技术质量部", "1005051729906521");
        table.put("槽神刘叫兽", "1005051764147817");
        table.put("贺炘", "1005052269686805");        

        for (String k : table.keySet()) {
            System.out.println("crawl"+ k + table.get(k));
            for (int i = 1; i < 11; i++) {
                driver.get("http://weibo.com/p/" + table.get(k)
                        + "/follow?relate=fans&page=" + i + "#place");
                //driver.get("http://weibo.com/p/" + table.get(k)
                //      + "/follow?page=" + i + "#place");
                List<WebElement> elements=new ArrayList<WebElement>();
                int timeout=0;
                while(true){
                    if(timeout>10){
                        break;
                    }
                    elements = driver.findElements(By
                            .xpath("//li[@class='clearfix S_line1']"));
                    if(elements.size()<5){
                        Thread.sleep(1000);         
                        timeout+=1;
                    }else{
                        break;
                    }                   
                }
                for (WebElement p : elements) {
                    WebElement info = p.findElement(By.xpath(".//div[@class='name']//a"));
                    System.out.println(k+"\tinteraction\t"+info.getText());
                }
            }
        }
    }

}

如果是使用新浪的 SDK. 需要高级认证, 代码也很简单, 官方有例子. 如下

package weibo4j.examples.friendships;

import weibo4j.Friendships;
import weibo4j.examples.oauth2.Log;
import weibo4j.model.User;
import weibo4j.model.UserWapper;
import weibo4j.model.WeiboException;

public class GetFollowers {
    public static void main(String[] args) {
        String access_token = args[0];
        Friendships fm = new Friendships();
        fm.client.setToken(access_token);
        String screen_name =args[1];
        try {
            UserWapper users = fm.getFollowersByName(screen_name);
            for(User u : users.getUsers()){
                Log.logInfo(u.toString());
            }
            System.out.println(users.getNextCursor());
            System.out.println(users.getPreviousCursor());
            System.out.println(users.getTotalNumber());
        } catch (WeiboException e) {
            e.printStackTrace();
        }
    }
}


↙↙↙阅读原文可查看相关链接,并与作者交流