实现网页计数器的好方法是什么?
从表面上看,这是一个简单的问题,但在处理搜索引擎爬虫和机器人、同一用户的多次点击、刷新点击时,就会出现问题。
具体来说,确保链接不只是通过反复点击被用户“点击”的好方法是什么?IP地址?饼干?这两者都有一些缺点(IP 地址不一定是唯一的,cookie 可以关闭)。
还有什么是存储数据的最佳方式?单独增加一个计数器或将每次点击作为记录存储在日志表中,然后偶尔进行汇总。
任何现场经验都会有所帮助,
+++ 瑞克 ---
实现网页计数器的好方法是什么?
从表面上看,这是一个简单的问题,但在处理搜索引擎爬虫和机器人、同一用户的多次点击、刷新点击时,就会出现问题。
具体来说,确保链接不只是通过反复点击被用户“点击”的好方法是什么?IP地址?饼干?这两者都有一些缺点(IP 地址不一定是唯一的,cookie 可以关闭)。
还有什么是存储数据的最佳方式?单独增加一个计数器或将每次点击作为记录存储在日志表中,然后偶尔进行汇总。
任何现场经验都会有所帮助,
+++ 瑞克 ---
将 IP 地址与会话结合使用。将 IP 地址的每个新会话计数为对您的计数器的一次点击。如果您认为需要查看这些数据,可以将其存储在日志数据库中。这对于计算您的网站何时获得最多流量、每天多少流量、每个 IP 等非常有用。
因此,我根据此处的评论对此进行了一些尝试。我想出的是在一个简单的领域计算一个计数器。在我的应用程序中,我有带有 Views 属性的代码片段实体。
当查看一个片段时,一个方法会过滤掉(白名单),这应该是浏览器:
public bool LogSnippetView(string snippetId, string ipAddress, string userAgent)
{
if (string.IsNullOrEmpty(userAgent))
return false;
userAgent = userAgent.ToLower();
if (!(userAgent.Contains("mozilla") || !userAgent.StartsWith("safari") ||
!userAgent.StartsWith("blackberry") || !userAgent.StartsWith("t-mobile") ||
!userAgent.StartsWith("htc") || !userAgent.StartsWith("opera")))
return false;
this.Context.LogSnippetClick(snippetId, IpAddress);
}
然后,存储过程使用一个单独的表来临时保存存储片段 ID、输入日期和 IP 地址的最新视图。每个视图都会被记录下来,当一个新视图出现时,它会检查相同的 IP 地址是否在过去 2 分钟内访问了这个片段。如果是这样,则不会记录任何内容。
如果是新视图,则会记录视图(同样是 SnippetId、IP、Entered),并且在 Snippets 表上更新实际的 Views 字段。
如果它不是一个新视图,那么该表将被清理,并记录任何超过 4 分钟的视图。这应该会导致在任何时候查看日志表中的条目数量最少。
这是存储过程:
ALTER PROCEDURE [dbo].[LogSnippetClick]
-- Add the parameters for the stored procedure here
@SnippetId AS VARCHAR(MAX),
@IpAddress AS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
-- check if don't allow updating if this ip address has already
-- clicked on this snippet in the last 2 minutes
select Id from SnippetClicks
WHERE snippetId = @SnippetId AND ipaddress = @IpAddress AND
DATEDIFF(minute, Entered, GETDATE() ) < 2
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO SnippetClicks
(SnippetId,IpAddress,Entered) VALUES
(@SnippetId,@IpAddress,GETDATE())
UPDATE CodeSnippets SET VIEWS = VIEWS + 1
WHERE id = @SnippetId
END
ELSE
BEGIN
-- clean up
DELETE FROM SnippetClicks WHERE DATEDIFF(minute,Entered,GETDATE()) > 4
END
END
这似乎工作得很好。正如其他人所提到的,这并不完美,但在初始测试中看起来已经足够好了。
如果我是你,我首先会放弃我的计数器是准确的。正如您所说,每种解决方案(例如 cookie、IP 地址等)往往都不可靠。所以,我认为你最好的选择是在你的系统中使用冗余:使用 cookie、“Flash-cookies”(共享对象)、IP 地址(可能与用户代理一起使用)和登录用户的用户 ID。
您可以实施某种方案,其中任何未知的客户端都被赋予一个唯一的 ID,该 ID 被存储(希望)在客户端的机器上并随每个请求重新传输。然后,您可以将 IP 地址、用户代理和/或用户 ID(以及您能想到的任何其他内容)绑定到每个唯一 ID,反之亦然。每次点击的时间戳和唯一 ID 都可以记录在某处的数据库表中,并且每次点击(至少每次点击到您的网站)都可能被允许或拒绝,具体取决于上次点击对于相同唯一 ID 的最近时间。这对于短期点击突发来说可能足够可靠,而长期而言无论如何都无关紧要(对于点击问题,而不是页面计数器)。
友好的机器人应该适当地设置他们的用户代理,并且可以根据已知的机器人用户代理列表(我在简单的谷歌搜索后在这里找到一个)进行检查,以便正确识别和处理与真人分开。
如果您开始使用 PHP,您可以使用会话来跟踪特定用户的活动。结合数据库,您可以跟踪来自特定 IP 地址的活动,您可能会认为这些地址是同一用户。
使用时间戳来限制点击次数(例如,假设每 5 秒点击不超过 1 次),并告诉网站何时发生新的“访问”(例如,如果最后一次点击是在 10 分钟前)。
您可能会发现 $_SERVER[] 属性可帮助您检测机器人或访问者趋势(例如浏览器使用情况)。
编辑:我之前跟踪过点击次数和访问次数,将页面查看计为点击次数,并在创建新会话时为访问次数 +1。它相当可靠(对于我使用它的目的来说已经足够可靠了。不支持 cookie 的浏览器(因此,不支持会话)和禁用会话的用户现在相当少见,所以我不会担心除非有理由过于准确。