User:Antigng-bot/redirect/report
这是我第二次因为bot错误的原因,在WP:VPO致歉了。前一次是在2015年的9月23日。
问题发生在我运行deleterd(也就是Wikipedia:机器人/申请/Antigng-bot/15)之时。处理这个任务之前,中文维基百科有66万个主名字空间内的重定向,其中7.6万个是繁简重定向,只有300个挂了{{简繁重定向}}的模板。需要为剩下的7万多个繁简重定向批量添加模板。我首先通过https://zh.wikipedia.org/w/api.php?action=query&format=xml&list=allredirects&arnamespace=0&arlimit=5000&arprop=ids|title获取所有主名字空间内的重定向的pageid和对应的重定向目标,然后分批地检查,每批X个(1<=X<=1000)。检查的时候先通过pageid找页面标题(https://zh.wikipedia.org/w/api.php?action=query&format=xml&pageids=XXX),然后检查该标题和重定向目标是否只是繁简差异,如果是,获取页面源码(https://zh.wikipedia.org/w/index.php?action=raw&redirect=no&title=),检查是否有模板,如果没有,加模板,提交编辑。
由于需要追踪每一笔编辑,便于发现错误,现在有三个过滤器限制该bot的编辑速率,不会超过每秒3次。(Special:滥用过滤器/188、Special:滥用过滤器/173、Special:滥用过滤器/181),我需要调整bot的编辑速率,既要避免大量触发过滤器,又要尽可能地快一些。(时间长了容易掉登录)显然X越大,编辑速率越快。(X=2,需要15个小时检查所有的重定向,而X=1000,需要30分钟。)所以我打算一开始取X=2,运行两次,处理掉大部分页面,然后取X=8,X=32......直至X=1000,清理完剩余页面。
但是在提高X的过程中我发现了一个问题,mw:API:allredirects返回的结果是按第一个字符的大小顺序排序的,而繁简重定向在里面的分布极为不均匀。导致我的bot有的时候好几分钟甚至好几十分钟没编辑,有时一下子出现大量的编辑(当然,这时就会被过滤器拦下来很多)。原来我以为低速处理掉大部分编辑后,分布会均匀一些,没想到越处理,分布就越不均匀。
所以我想了一个办法,在查询mw:API:allredirects的时候把获得的结果打散,这样就不会出现堆积的情况。(如果再堆积调个参数就是了)但由于查询结果中既有pageid又有重定向目标,不好对付,我把pageid和重定向标题写在了一个字符数组里面:
sprintf(line,"%s %s",pageid,target);
弄乱之后再通过
sscanf(line,"%s %s",pageid,target);
取回pageid和重定向目标。
这样修改完之后我没能测试出错误,然后就放心地去让它运行了。跑完一遍之后我注意到https://tools.wmflabs.org/antigng-bot/log.txt里面出了一些变化,没打散查询结果之前会检测出7.6万繁简重定向,打散之后只检测出7.1万繁简重定向。由于做这样修改的同时我也把X从200调到了1000,所以我当时误以为是cp1008.wikimedia.org或api应用程序服务器受不了1000的并发量,开始大量报错。(之前做别的任务,取X=1000的时候,进入API应用程序服务器的总请求数会增加20%,cpu使用率增加3%)所以就没管他。就这样跑到不再出新编辑为止。([1])
昨天我又跑了一遍,发现了两笔错误的编辑([2][3])。我检查了log.txt,发现竟然没有一个带 “()”的标题,这才意识到mw:API:allredirects返回的结果里页面标题可能会出现空格(而不是下划线),这样一来麻烦大了:
//现在pageid="588624", target="激進黨 (法國)"
sprintf(line,"%s %s",pageid,target);
//line变成了 "588624 激進黨 (法國)"
/*
do something
*/
sscanf(line,"%s %s",pageid,target);
//现在pageid="588624", target="激進黨",之后程序就会误以为id为588624的页面是一个繁简重定向
我当时还抱有一丝侥幸心理,认为这样的错误不会太多,只是修改了程序,重新跑了两遍,果然跑出来许多带 “()”的页面。
这之后发现Category:簡繁重定向里面居然有7.7万个页面,比log.txt多出300多个!这才知道出错的页面并不少。幸好4/13日跑完之后留下的log我没删掉,我找出了那份log里面有,而现在的log里面没有的页面,整理在了User:Antigng-bot/redirect/bug,并全部予以手动回退。
从发生的过程可以看出,其实这个错误完全是可以避免的。如果仔细研究一下Allredirect返回的结果,如果修改之后多做一些测试,如果发现log异常后多做些探究,它本不该发生。责任在我。
造成的不便,请大家原谅。