MySQL / PHP从表格时间戳

时间:2016-03-15 17:45:33

标签: mysql sql

我有一个MySQL表,用于记录访问者统计信息以及他们在每个页面上的时间。我试图做的是计算出选择的时间戳之间的频率,以确定它是一个人类访问者还是一个糟糕的刮刀机器人。

机器人显然可以比人类访问者更快地在页面之间移动,因此时间戳每1-2秒左右就有一次页面访问,这可以一次持续大约2个小时(很多这些机器人也会增加服务器负载。)

然后计划是使用PHP并对结果做一些事情,或者可能使用单个SQL查询完成所有操作,以查看某个IP在过去2分钟内访问过的频率,以及是否&#39 ;频率或时​​间差仅相当于页面视图之间的秒数,然后将该IP放在机器人列表中。

我已经尝试了TIMESTAMPDIFF,如果与多个SQL语句结合使用MAXMIN,可能会有效,然后在PHP中提取并构建回来新的查询,但我试图以最有效的方式解决这个问题。

我首先尝试使用LIMITOFFSET以及MINMAX制作子查询,但它太混乱了!

所以现在我一直在尝试INTERVAL,但我不确定它是否正在做我期望或需要的事情。

SELECT
    `id`, `ip_addr`, `time_viewed`, UNIX_TIMESTAMP(`time_viewed`)  AS unix, 
     UNIX_TIMESTAMP(NOW()) as NOWWW,  (UNIX_TIMESTAMP(NOW()) - 120) as one20
         FROM `page_counter`
         WHERE `ip_addr` = '127.0.0.1' AND DATE_ADD(curdate(),INTERVAL 10 SECOND)
         ORDER BY `time_viewed` DESC
         LIMIT 0, 9

据我所知,在让自己过于混淆之前就已经有了!

任何帮助都会很棒。

编辑/更新信息

好的,所以我昨晚有点匆匆写了很多,所以我现在试着更好地澄清一下我希望实现的目标。

某些糟糕的机器人遇到了我的网站,并且在大约2个小时的时间内正在进行近200次页面点击。看看统计数据,我可以看到几乎每个页面都有相同的IP,每次点击之间只有几秒钟。

在某些情况下,他们在30秒内访问了近10页,这是从统计数据的角度来看,不太可能是人类行为。

所以我的目标是尽可能尝试检测此行为,然后将机器人重定向到特定页面,或至少从统计信息中阻止其IP。

我的第一个想法是使用TIMESTAMPDIFF,但我认为这需要多个查询才能实现(因此这个问题的PHP方面可以过滤结果)。

例如:

SELECT
    `id`, `ip_addr`, `time_viewed`
        FROM `page_counter`
        WHERE `ip_addr` = '109.86.72.137'
        ORDER BY `time_viewed` DESC
        LIMIT 0, 9

然后返回此IP已命中的最后9个页面以及查看的时间:

id       ip_addr        time_viewed 
1587039 109.86.72.137   2016-03-15 15:20:50
1587038 109.86.72.137   2016-03-15 15:20:45
1587037 109.86.72.137   2016-03-15 15:20:41
1587036 109.86.72.137   2016-03-15 15:20:38
1587035 109.86.72.137   2016-03-15 15:20:29
1587034 109.86.72.137   2016-03-15 15:20:27
1587033 109.86.72.137   2016-03-15 15:20:22
1587032 109.86.72.137   2016-03-15 15:20:15
1587031 109.86.72.137   2016-03-15 15:20:14

然后使用此信息,或者如果它可能被限制为1分钟内的所有页面,如果可以采用第一个和最后一个时间戳,然后在TIMESTAMPDIFF查询中使用,如下所示:

SELECT
    `id`, `ip_addr`, `time_viewed`, TIMESTAMPDIFF(SECOND,'2016-03-15 15:20:14', '2016-03-15 15:20:50') AS diff
         FROM `page_counter`
         WHERE `ip_addr` = '109.86.72.137'
         GROUP BY `ip_addr`
         ORDER BY `time_viewed` DESC

然后返回:

id      ip_addr         time_viewed         diff    
1586571 109.86.72.137   2016-03-15 13:02:34 36

所以这个特殊的IP在36秒内访问了9个页面,这很可能是机器人的行为。

我的问题是能够从LIMIT查询动态获取这些第一个和最后一个时间戳,然后将其提供给TIMESTAMPDIFF查询。我不知道是否有更好的方法来尝试获取这些信息,或者通过这样的行为来确定访问者是否可能是机器人,所以我对这些想法持开放态度,更好的实现方法(纯粹在MySQL或PHP组合中)。

编辑#2 我忘记提及的东西,实际上可能对此有所帮助 - 我也跟踪每位访客的会话ID,所以也许这可能会影响过滤过程?

编辑#3 - 会话ID 考虑到更多,会话跟踪可能是解决此问题的最佳方式:

SELECT
    `id`, `ip_addr`, `time_viewed`, COUNT(`sessionID`) as sesh
         FROM `page_counter`
         WHERE `ip_addr` = '109.86.72.137' AND DATE(time_viewed) = '2016-03-15'
         ORDER BY `time_viewed` DESC

返回:

id      ip_addr         time_viewed         sesh
1586571 109.86.72.137   2016-03-15 13:02:34 172

这意味着单个IP在该日的范围内有172个唯一会话。这本身就使它更像是一个机器人,而不是人类访问者,这可能是更简单的跟踪方式(显然这取决于网站流量,但我不希望一个IP地址可以获得这么多会话有一天??)

编辑(再次)DISTINCT添加到COUNT只会返回此IP的15个唯一会话,这可能更接近人类行为(?)

使用trincot的示例进行更新:

SELECT     ip_addr, 
           DATE_FORMAT(time_viewed, '%Y-%m-%d %h') AS hour,
           COUNT(*) AS page_visits,
           (MAX(UNIX_TIMESTAMP(time_viewed)) - MIN(UNIX_TIMESTAMP(time_viewed))) 
               / COUNT(*) AS avg_seconds_between
FROM       page_counter
GROUP BY   ip_addr, DATE_FORMAT(time_viewed, '%Y-%m-%d %h')
HAVING     page_visits > 9
ORDER BY   4
LIMIT      9

结果:

ip_addr         hour            page_visits avg_seconds_between 
8.37.231.185    2016-01-01 02   35          0.2286
185.5.52.121    2016-03-15 01   324         0.3117
199.15.233.180  2014-03-11 04   22          0.3636
199.15.233.139  2014-03-10 08   22          0.4091
199.15.233.137  2014-01-29 08   12          0.4167
199.15.233.139  2014-02-13 06   12          0.4167

1 个答案:

答案 0 :(得分:1)

这足以得到你想要的东西:

@Override
public float getPageWidth(int position) {
    return 0.75f;
}

根据IP地址计算在过去10秒内查询了多少页。页面浏览量最多的人将列在顶部。

要在更长的时间段内获得视图,您可以按小时对统计信息进行分组,然后在顶部选择访问率最高的统计信息。我没有测试过这个:

SELECT   ip_addr, count(*)
FROM     page_counter
WHERE    time_viewed >= DATE_ADD(curdate(), INTERVAL -10 SECOND)
GROUP BY ip_addr
ORDER BY 2 DESC
LIMIT    9

可能需要调整SELECT ip_addr, DATE_FORMAT(time_viewed, '%Y-%m-%d %h') AS hour, COUNT(*) AS page_visits, (MAX(UNIX_TIMESTAMP(time_viewed)) - MIN(UNIX_TIMESTAMP(time_viewed))) / COUNT(*) AS avg_seconds_between FROM page_counter GROUP BY ip_addr, DATE_FORMAT(time_viewed, '%Y-%m-%d %h') HAVING page_visits > 9 ORDER BY 4 LIMIT 9 子句以使用更能反映您需求的限制。它检查在一小时内记录的页面访问样本是否足以得出任何结论。

因此,如果机器人在14:55开始工作,在15:00之前只有4次页面访问,那么小时槽14:xx将无法检测到它,但如果在下一个小时槽中检测到它,在接下来的30分钟(例如)中继续这样。