使用者: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異常後多做些探究,它本不該發生。責任在我。
造成的不便,請大家原諒。