博客中的阅读量是如何设计的?

在博客园中,一篇博客的底部,通常有该篇博客的阅读量的统计。当浏览器端没发起一个请求的时候,它通过相应的逻辑判断,如果符合要求,则给阅读量加一。所以,有了如下代码:

package test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class Url {

    private final static String BLOGURL = "http://www.cnblogs.com/RunForLove/p/5439002.html";

    public static void main(String args[]) {
        try {
            for (int i = 0; i > -1; i++) {
                execute(BLOGURL);
                System.err.println("cnblogs\t" + i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void execute(String url) throws Exception {
        // 创建URL链接
        URL connURL = new URL(url);
        // 打开链接
        HttpURLConnection httpConn = (HttpURLConnection) connURL.openConnection();

        String cookie = getCookie();

        // 设置通用属性
        httpConn.setRequestProperty("Accept",
                                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        httpConn.setRequestProperty("Accept-Encoding", "gzip, deflate, sdch");
        httpConn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
        httpConn.setRequestProperty("Cache-Control", "max-age=0");
        httpConn.setRequestProperty("Connection", "Keep-Alive");
        httpConn.setRequestProperty("Cookie", cookie);
        httpConn.setRequestProperty("Host", "www.cnblogs.com");
        httpConn.setRequestProperty("User-Agent",
                                    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36");
        httpConn.setRequestProperty("If-Modified-Since", "Wed, 11 May 2016 09:24:05 GMT");

        // 建立实际的链接
        httpConn.connect();
        BufferedReader in = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "UTF-8"));
        in.close();

    }

    private static String getCookie() {
        return "CNZZDATA4324368=cnzz_eid%3D1585339881-1456207541-null%26ntime%3D1456207620; CNZZDATA1556060=cnzz_eid%3D412661198-1456450586-null%26ntime%3D1456450586; CNZZDATA5299104=cnzz_eid%3D1116436150-1456733240-null%26ntime%3D1456733240; __gads=ID=bd2ad73bc51c0d10:T=1456882812:S=ALNI_Mayf4iI2fnDbt6M7y9cprjSo8kzzQ; .CNBlogsCookie=900FD4817DFA0E06C5C5CB79015C39CC3C869C4324CBA33194A920C4639F2843E32BCA929484834CC0B1C653661BB1CF7AFC54E30A77E3F2B95BB160AEB17E0AC438B8C30CDD84DFC2455CE2D3F5B06B04881C61; AJSTAT_ok_times=3; CNZZDATA1121896=cnzz_eid%3D2087772282-1462859238-null%26ntime%3D1462859238; CNZZDATA943648=cnzz_eid%3D1056946870-1462854976-null%26ntime%3D1462859947; __utma=226521935.1056844361.1456278785.1462950083.1462950083.1; __utmc=226521935; __utmz=226521935.1462950083.1.1.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _ga=GA1.2.1056844361.1456278785";
    }
}

但是,通过测试,博客园中的阅读量并没有增加。我的思考如下:
1.它的后台做了时间戳的判断,如果相同的IP在很短的时间内访问,阅读数不加。(之所以这么设计,可能是需要将缓存写回数据库)但是,跑了好长是代码,依旧没有阅读量增加。
2.特别好奇博客园的后台是怎么统计阅读数的,有没有做过类似项目的,讲讲啊。

非常感谢~ 谢谢~~

阅读 15.6k
13 个回答

简单谈下思路,供楼主参考
1)简单粗暴型的,这里不用去管浏览器的user-agent,不管cookie等信息,每产生一次PV,就直接计数,优点:简单,缺点:可能不真实,也可能有刷量数据
2)稍微细腻点的统计,会区分新老用户,楼主你可以研究下baidu统计的SDK,里面包含有用户的浏览器信息,操作系统信息、用户的地域信息等,也就是说,你通过浏览器的javascript以及和服务器数据的交互,对于后台服务器来说,是可以获取这些数据的,那么对于博客园这样的网站,他可能想要统计到真实的用户访问情况,以便有些行为分析以便精准投放推荐博客(这个纯粹是我猜测的,我没研究过、关注过博客园的技术,但目前很多做推荐算法的大多是根据cookie来精确投放广告),这时会结合用户的IP信息、cookie信息(也就是session)和user-agent来统计分析,注意,这里的IP是映射后的IP地址(如果这里不清楚什么是映射后的IP地址,建议百度搜索下NAT地址),对于我们日常的家庭拨号上网,都是拿到的运营商的虚拟出来的内网地址,以便节省IPv4资源,所以说,一个user-agent、IP、cookie基本上能唯一标识一个用户信息。不过我看了下博客园,貌似没有用到cookie数据。

clipboard.png

3) 进一步说,有了这些数据之后,从设计角度来说,阅读量的这个信息在页面展现中不是优先级最高的(优先级最高的应该是博客文章内容),但阅读量的相关信息是有意的,那么问题来了,对于阅读量这种信息是否在数据库的设计层面上要加写锁去互斥? 这里推荐楼主了解下什么是CAP原理,可以看下
http://www.blogjava.net/hello-yun/archive/2012/04/27/376744.html

4) 其他的回复已经提到了,可能是缓存,也可能是有IP的判断、cookie的检测,这个要尝试之后才知道了,不过个人觉得可能性最大的是这个阅读量,博客园采用的是一个异步统计的办法,也就是说你产生真实的阅读之后,他是经过后台处理之后才给阅读量计数器+1的

希望能帮助到你。

这个统计没有绝对的正确,只能尽量去接近正常的统计算法,且不被人恶意去刷!

所以他不是你说的相同的IP在很短的时间内不计算在内,而是做了一个IP最多只增加两次阅读类似的机制,或者还有更深一层次的,比如第二天IP清空,然后这个统计算法变成了每一天每一个IP都有两次阅读次数增加的机会

所以我觉得只要你认为这个符合你系统的业务设计就是合理的,没有标准答案!

不同的博客系统设计是不一样的。

  1. 最简单的是每请求一次增加一次阅读量。

  2. 稍微高级点用session记录用户,一段固定时间内(比如30分钟),不管你用同一个浏览器内核访问多少次只增加一次阅读量。

  3. 再高级点,一段固定时间内(比如30分钟),同一个ip访问不论多少次只增加一次阅读量。

  4. 再高级就是设计上的问题了,比如只有将文章从上读到下才算一次阅读量,只有登录用户浏览才算阅读量等等。

同一客户端一段时间内多次访问当成一次访问,说白了就是统计页面的 PV 嘛。

我的方法很简单,就是点进这个链接,在数据库里加一

我们以前做的是一小时内的同一个IP的只算一次

用session吧,简单好用。
例如我昨天就会用这个来统计:

    // 文章访问量统计
    $article_id=$_GET['id'];
    setcookie("ready_".$article_id,"1",time()+864000);//设置一天访问量+1
    if(!isset($_COOKIE["ready_".$article_id])){
        require_once("db.php");
        $sql_ready_add = "update article set ready=ready+1 where id=".$article_id;
        $result_ready_add=$mysqli->query($sql_ready_add);
    }

有个东西叫缓存?

主要是看运营的小伙伴怎么定义。打个比方,如果是初创企业,要拿各种流量数据去忽悠风投,那么你懂的~如果是成熟的项目,为了进一步的数据分析/挖掘,那么对数据的严谨度会更高

校验user-agent、cookie等信息;每一次浏览插入一条访客记录到A表

一般会基于session, 其实session的本质就是个自定义的cookie,一般人不会闲得无聊去删cookie Java教程

我是做微博的,我说说微博的做法。

阅读量,点赞数,单访问限制。都是用redis实现的。
然后每天夜里空闲时段同步数据库(按一定规则,分批等)。

如果用户已经登录,只统计一次;
如果是游客,则根据IP、timestamp、cookie等综合判断,相同就只统计一次。
这样可以防止刷浏览量。

Update:我自己开发的某项目中包括博客功能,将会使用这个方法防止刷浏览量。

推荐问题
宣传栏