自定义采集数据实现

自定义采集数据实现

1.原理分析

                                       ## 采集数据原理图                                                                      

在这里插入图片描述

  1. 执行流程用户的行为会触发浏览器对被统计页面的一个http请求,比如打开某网页。当网页被打开,页面中的埋点javascript代码会被执行。
  2. 埋点:在网页中预先加入小段javascript代码,这个代码片段一般会动态创建一个script标签,并将src属性指向一个单独的js文件,此时这个单独的js文件(图中绿色节点)会被浏览器请求到并执行,这个js往往就是真正的数据收集脚本。
  3. 数据收集完成后,js会请求一个后端的数据收集脚本(图中的backend),这个脚本一般是一个伪装成图片的动态脚本程序,js会将收集到的数据通过http参数的方式传递给后端脚本,后端脚本解析参数并按固定格式记录到访问日志,同时可能会在http响应中给客户端种植一些用于追踪的cookie。

2.收集的信息

2.1设计原理图

在这里插入图片描述

2.2.确定收集信息
名称 途径 备注
访问时间 web server Nginx $msec
IP web server Nginx $remote_addr
域名 javascript document.domain
URL javascript document.URL
页面标题 javascript document.title
分辨率 javascript window.screen.height & width
颜色深度 javascript window.screen.colorDepth
Referrer javascript document.referrer
浏览客户端 web server Nginx $http_user_agent
客户端语言 javascript navigator.language
访客标识 cookie Nginx $http_cookie
网站标识 javascript 自定义对象
状态码 web server Nginx $status
发送内容量 web server Nginx $body_bytes_sent

2.3确定埋点代码

<script type="text/javascript">
  var _maq = _maq || [];
  _maq.push(['_setAccount', 'UA-XXXXX-X']);
  (function() {
    var ma = document.createElement('script'); ma.type = 'text/javascript'; ma.async = true;
    ma.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ma.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ma, s);
  })();
</script>

注释:其中_maq是全局数组,用于放置各种配置,其中每一条配置的格式为:
_maq.push([‘Action’, ‘param1’, ‘param2’, …]);
_maq的机制不是重点,重点是后面匿名函数的代码,这段代码的主要目的就是引入一个外部的js文件(ma.js),方式是通过document.createElement方法创建一个script并根据协议(http或https)将src指向对应的ma.js,最后将这个元素插入页面的dom树上。
注意ma.async = true的意思是异步调用外部js文件,即不阻塞浏览器的解析,待外部js下载完成后异步执行。这个属性是HTML5新引入的。
js自调用匿名函数 >格式:(function(){})();

2.4 前端数据收集脚本

数据收集脚本(ma.js)

(function () {
    var params = {};
    //Document对象数据
    if(document) {
        params.domain = document.domain || ''; 
        params.url = document.URL || ''; 
        params.title = document.title || ''; 
        params.referrer = document.referrer || ''; 
    }   
    //Window对象数据
    if(window && window.screen) {
        params.sh = window.screen.height || 0;
        params.sw = window.screen.width || 0;
        params.cd = window.screen.colorDepth || 0;
    }   
    //navigator对象数据
    if(navigator) {
        params.lang = navigator.language || ''; 
    }   
    //解析_maq配置
    if(_maq) {
        for(var i in _maq) {
            switch(_maq[i][0]) {
                case '_setAccount':
                  params.account = _maq[i][1];
                  break;
                default:
                  break;
            }   
        }   
    }   
    //拼接参数串
    var args = ''; 
    for(var i in params) {
        if(args != '') {
            args += '&';
        }   
        args += i + '=' + encodeURIComponent(params[i]);
    }   
  
    //通过Image对象请求后端脚本
    var img = new Image(1, 1); 
    img.src = 'http://xxx.xxxxx.xxxxx/log.gif?' + args;
})();

2.5 后端脚本
##log.gif是后端脚本,是一个伪装成gif图片的脚本。后端脚本一般需要完成以下几件事情:
1、解析http请求参数得到信息。
2、从Web服务器中获取一些客户端无法获取的信息,如访客ip等。
3、将信息按格式写入log。
4、生成一副1×1的空gif图片作为响应内容并将响应头的Content-type设为image/gif。
5、在响应头中通过Set-cookie设置一些需要的cookie信息。

我们使用nginx的access_log做日志收集,不过有个问题就是nginx配置本身的逻辑表达能力有限,所以选用OpenResty做这个事情。
OpenResty是一个基于Nginx扩展出的高性能应用开发平台,内部集成了诸多有用的模块,其中的核心是通过ngx_lua模块集成了Lua,从而在nginx配置文件中可以通过Lua来表述业务。
Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

首先,需要在nginx的配置文件中定义日志格式:

log_format tick 
"$msec||$remote_addr||$status||$body_bytes_sent||$u_domain||$u_url||$u_title||$u_referrer||$u_sh||$u_sw||$u_cd||$u_lang||$http_user_agent||$u_account";

注意这里以u_开头的是我们待会会自己定义的变量,其它的是nginx内置变量。然后是核心的两个location:

location / log.gif {
    #伪装成gif文件
    default_type image/gif;    
    #本身关闭access_log,通过subrequest记录log
    access_log off;
  
    access_by_lua "
        -- 用户跟踪cookie名为__utrace
        local uid = ngx.var.cookie___utrace        
        if not uid then
            -- 如果没有则生成一个跟踪cookie,算法为md5(时间戳+IP+客户端信息)
            uid = ngx.md5(ngx.now() .. ngx.var.remote_addr .. ngx.var.http_user_agent)
        end 
        ngx.header['Set-Cookie'] = {'__utrace=' .. uid .. '; path=/'}
        if ngx.var.arg_domain then
            -- 通过subrequest子请求到/i-log记录日志,将参数和用户跟踪cookie带过去
            ngx.location.capture('/i-log?' .. ngx.var.args .. '&utrace=' .. uid)
        end 
    ";  
  
    #此请求资源本地不缓存
    add_header Expires "Fri, 01 Jan 1980 00:00:00 GMT";
    add_header Pragma "no-cache";
    add_header Cache-Control "no-cache, max-age=0, must-revalidate";
    #返回一个1×1的空gif图片
    empty_gif;
}   
  
location /i-log {
    #内部location,不允许外部直接访问
    internal;
  
    #设置变量,注意需要unescape,来自ngx_set_misc模块
    set_unescape_uri $u_domain $arg_domain;
    set_unescape_uri $u_url $arg_url;
    set_unescape_uri $u_title $arg_title;
    set_unescape_uri $u_referrer $arg_referrer;
    set_unescape_uri $u_sh $arg_sh;
    set_unescape_uri $u_sw $arg_sw;
    set_unescape_uri $u_cd $arg_cd;
    set_unescape_uri $u_lang $arg_lang;
    set_unescape_uri $u_account $arg_account;
    #打开日志 
    log_subrequest on;
    #记录日志到ma.log 格式为tick
    access_log /path/to/logs/directory/ma.log tick;
  
    #输出空字符串
    echo '';
}

2.6 2.6.日志切分
日志收集系统访问日志时间一长文件变得很大,而且日志放在一个文件不便于管理。通常要按时间段将日志切分,例如每天或每小时切分一个日志。通过crontab定时调用一个shell脚本实现,如下:

_prefix="/path/to/nginx"
time=`date +%Y%m%d%H`
mv ${_prefix}/logs/ma.log ${_prefix}/logs/ma/ma-${time}.log
kill -USR1 `cat ${_prefix}/logs/nginx.pid `

这个脚本将ma.log移动到指定文件夹并重命名为ma-{yyyymmddhh}.log,然后向nginx发送USR1信号令其重新打开日志文件。
USR1通常被用来告知应用程序重载配置文件, 向服务器发送一个USR1信号将导致以下步骤的发生:停止接受新的连接,等待当前连接停止,重新载入配置文件,重新打开日志文件,重启服务器,从而实现相对平滑的不关机的更改。
cat ${_prefix}/logs/nginx.pid 取 nginx 的进程号
然后再/etc/crontab里加入一行:

59  *  *  *  * root /path/to/directory/rotatelog.sh

在每个小时的59分启动这个脚本进行日志轮转操作。

补充:关于日志中文乱码
修改源码并重新编译
在源码:nginx-1.8.1/src/http/modules/ngx_http_log_module.c

ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
{
    ngx_uint_t      n;
    //注释1
    /*static u_char   hex[] = "0123456789ABCDEF";*/

    static uint32_t   escape[] = {
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */

                    /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
        0x00000004, /* 0000 0000 0000 0000  0000 0000 0000 0100 */

                    /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
        0x10000000, /* 0001 0000 0000 0000  0000 0000 0000 0000 */

                    /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
        0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */

        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
    };


    if (dst == NULL) {

        /* find the number of the characters to be escaped */

        n = 0;

        while (size) {
            if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
                n++;
            }
            src++;
            size--;
        }

        return (uintptr_t) n;
    }
    
    while (size) {
    //注释2
        /*if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
            *dst++ = '\\';
            *dst++ = 'x';
            *dst++ = hex[*src >> 4];
            *dst++ = hex[*src & 0xf];
            src++;

        } else {
            *dst++ = *src++;
        }*/
        *dst++ = *src++;
        size--;
    }

    return (uintptr_t) dst;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TDX(通达信)是一种常用的股票交易软件,它具备丰富的数据分析功能。TDX自定义数据采集是指用户可以根据自己的需求,通过编程或设置规则,实现对特定数据采集和整合。 TDX自定义数据采集实现可以通过编写相应的脚本或插件来完成。用户可以利用TDX软件提供的API接口,编写脚本来自动采集他们关心的数据。这些数据可以是股票的行情数据、交易数据、财务数据等。用户可以根据自己的需求进行自定义,提取所需的数据并进行进一步的分析。 此外,TDX软件还支持用户通过设置规则实现数据采集。用户可以设置某个特定条件下,自动采集指定数据。例如,用户可以设置当某只股票的涨跌幅超过一定阈值时,自动采集该股票的相关数据。这样,用户可以方便地获取重要的市场信息,并据此做出相应的投资决策。 TDX自定义数据采集的好处在于能够满足用户个性化的需求。用户可以按照自己所关注的领域或特定策略,在TDX软件上自定义数据采集功能,快速获取所需的数据。用户可以针对自己的投资目标、风险偏好等进行数据筛选和整理,提高交易决策的准确性和效率。 总而言之,TDX自定义数据采集为用户提供了在股票交易中获取个性化数据的便利性。用户可以通过编写脚本或设置规则,实现对特定数据采集和整合,提高投资决策的准确性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值