Typecho 的 Initial 主题阅读次数统计排除蜘蛛爬虫的影响
后台看到安装的蜘蛛日志一个多月产生了 20 万的日志,看着网站的访问量也没怎么增加,但分布的文章都会有一定的阅读数,且随时间迁移,越积越多。好奇 Typecho 的 Initial 主题阅读次数统计是否会受到蜘蛛爬虫的影响,让 chatgpt 帮我分析找到了返回阅读数显示的方法:
# functions.php
function Postviews($archive) {
$db = Typecho_Db::get();
$cid = $archive->cid;
if (!array_key_exists('views', $db->fetchRow($db->select()->from('table.contents')))) {
$db->query('ALTER TABLE `'.$db->getPrefix().'contents` ADD `views` INT(10) DEFAULT 0;');
}
$exist = $db->fetchRow($db->select('views')->from('table.contents')->where('cid = ?', $cid))['views'];
if ($archive->is('single')) {
$cookie = Typecho_Cookie::get('contents_views');
$cookie = $cookie ? explode(',', $cookie) : array();
if (!in_array($cid, $cookie)) {
$db->query($db->update('table.contents')
->rows(array('views' => (int)$exist+1))
->where('cid = ?', $cid));
$exist = (int)$exist+1;
array_push($cookie, $cid);
$cookie = implode(',', $cookie);
Typecho_Cookie::set('contents_views', $cookie);
}
}
echo $exist == 0 ? '暂无阅读' : $exist.' 次阅读';
}可以看到统计主要是通过将文章的 cid 写入到 cookie 中的,这样下次再次阅读的时候可以排除,不会重复统计。但显然,没有排除爬虫的访问。
一直很好奇谷歌和百度这样的搜索引擎,是如何精确统计 PV、UV 的。问了 chatgpt,主要还是一些参数做成的“综合指纹”,并且因为大部分爬虫都只爬页面结构,js 等文件是排除在外的。这就让搜索引擎的统计,只有在浏览器之类的客户端加载进来才会发出。
并且这里针对是文章 cid,而搜索引擎的统计是针对的所有收录的页面,根据访问路径再细分请求。各种参数都会对统计结果有印象,比如清一下缓存,或者切一下 VPN,所以结果只能是尽量精确。
- Cookie
- Session
- IP + UA
- Visitor ID
最后是 php 增加排除蜘蛛爬虫方法:
function isBot() {
$bots = [
'bot',
'spider',
'crawl',
'slurp',
'Baiduspider',
'Googlebot',
'bingbot',
'YandexBot',
'Bytespider',
'Sogou',
'360Spider'
];
return preg_match(
'/'.implode('|', $bots).'/i',
$_SERVER['HTTP_USER_AGENT'] ?? ''
);
}
function Postviews($archive) {
$db = Typecho_Db::get();
$cid = $archive->cid;
// if (!array_key_exists('views', $db->fetchRow($db->select()->from('table.contents')))) {
// $db->query('ALTER TABLE `'.$db->getPrefix().'contents` ADD `views` INT(10) DEFAULT 0;');
// }
$exist = $db->fetchRow($db->select('views')->from('table.contents')->where('cid = ?', $cid))['views'];
if ($archive->is('single') && !isBot()) {
$cookie = Typecho_Cookie::get('contents_views');
$cookie = $cookie ? explode(',', $cookie) : array();
if (!in_array($cid, $cookie)) {
$db->query($db->update('table.contents')
->rows(array('views' => (int)$exist+1))
->where('cid = ?', $cid));
$exist = (int)$exist+1;
array_push($cookie, $cid);
$cookie = implode(',', $cookie);
Typecho_Cookie::set('contents_views', $cookie);
}
}
echo $exist == 0 ? '暂无阅读' : $exist.' 次阅读';
} 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
海滨擎蟹
微信
支付宝