維基百科:製作機器人

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

機器人是一種與維基百科互動的自動程序,就好像他們是人類編輯者一樣。這個頁面將解釋如何製作一個用於維基百科的機器人。此頁面主要適用於那些擁有編程經驗,但不知道如何使用它們來創建維基機器人的用戶。

為何需要機器人?

機器人以比人類快得多的速度執行任務。如果你需要完成一些簡單但冗長的工作(比如當你需要添加模板到某個類別的1000多個條目里時),那麼這種工作更適合讓機器人而不是人類來進行。

製作機器人前先仔細想好

維基百科中已經有一些機器人正在運行。其中許多機器人開放了源代碼,以便於在某些情況下使用這些源代碼縮短新機器人的開發時間。另外,維基百科還有對所有用戶開放使用的一些半機器人英語Wikipedia:Semi-bots。它們之中的大多數是擁有維基相關特殊功能的加強瀏覽器。其中最常使用的便是自動維基瀏覽器。請參見維基百科:維基百科工具以獲得完整列表。

如果你沒有先前的編程經驗,更簡單的辦法是請求一個已有的機器人來完成你的工作,或者請求其他人為你編寫一個機器人。這類請求可以在Wikipedia:機器人/作業請求中提出。如果你一定要自己編寫一個機器人,一定記住學習一門程序語言並不是一個簡單的任務。無論如何,這並不是黑魔法-只要花費足夠的時間和努力,任何人都可以學會如何編程,祝你好運!

如果你決定去創建一個機器人,那麼創建一個無錯誤、高效且有用的機器人是非常重要的。下面的初步考慮是重要的:

  • 這個機器人將會是人工輔助的還是全自動的?
  • 你會獨自一個人創建一個機器人,還是利用其他編程者的幫助?
  • 你將使用什麼程序語言來開發這個機器人?
  • 這個機器人的請求,編輯,或是其它行為會不會被記錄?如果是,那麼這些記錄是存儲在本地,還是維基頁面上?
  • 這個機器人是運行於瀏覽器之中(比如,用JavaScript編寫),或者是一個獨立的程序?
  • 如果是一個獨立程序,這個機器人將會在你的電腦本地運行,還是在一個類似維基媒體工具服務器的遠程服務器上運行?
  • 如果是在遠程服務器上運行,其他的編者是否能啟動或操作這個機器人?

維基機器人的工作原理

概論

就像人類編輯者一樣,一個維基百科機器人閱讀維基百科上的頁面,對它認為需要做出變化的地方進行改變。不同之處在於儘管機器人更快並且不會像人類一樣容易疲倦,他們並不像我們一樣聰明。機器人適用於固定模式的、不需作出決策的重複工作。

在最典型的情況下,機器人登入它自己的帳號並像一個瀏覽器一樣請求維基百科的頁面。它不會在顯示屏上顯示頁面,而是在內存中工作。接下來它會程序化地分析頁面代碼以確定是否需要作出改變。然後它會再次像一個瀏覽器一樣做出它被設計做出的改動並提交更改。

因為機器人以與普通人相同的方式訪問頁面,它們會體驗到和人類用戶一樣的困難。他們會捲入編輯衝突,遇到頁面延遲,或者遇到其它請求或編輯頁面時可能遇到的並發錯誤。因為機器人的工作量遠遠大於一個普通的人,它們更容易遇到這些問題。因此,當編寫一個機器人時,對這些情況的考慮是必要的。

用API寫機器人

為了對維基百科頁面作出更改,機器人有必要從維基百科檢索頁面並且提交編輯。一些應用程序接口可以被用於這個目的。

  • MediaWiki APIs (api.php)。該庫用於製作自動處理查詢和提交更改的機器人。可以接受多種機器可讀的格式如JSONXMLYAML等。其特性在舊版的查詢API接口可以找到,參見API手冊
狀態:在所有維基媒體項目中可用,包含很全的查詢集。通過api.php編輯頁面適用於所有維基媒體項目,這允許機器人在沒有屏幕抓取英語Screen scraping的情況下工作。
  • 屏幕抓取英語Screen scraping (index.php)。屏幕抓取用於請求維基頁面,查看HTML源代碼(和你在大多數瀏覽器中點擊查看-頁面源代碼所看到的一樣),之後分析HTML的特性。許多問題可能會在其中發生:維基百科界面可以在毫無提示的情況下改變,這可能會破壞機器人的代碼,獲取HTML的請求對處理維基文本本身對服務器的壓力也更大。當你請求一個頁面的精簡版本(無維基側邊欄和標籤欄)以減少數據傳輸並減小用戶界面更改的影響時,你可以包含代碼action=render GET請求 w/index.php?title=Wikipedia:...&action=render 。index.php的其他參數也可能會有幫助:參見列表index.php參數手冊。在API有如此多特性的情況下,幾乎沒有理由再使用這種技術了,這種技術主要用於較古老的機器人框架。
狀態: 不鼓勵使用。
狀態: MediaWiki的內置特性,在所有維基媒體服務器上均能使用。
  • 原生(維基文本)頁面處理。使用action=rawaction=raw&templates=expand GET請求到index.php可以獲取一個頁面未處理過的維基文本源碼。帶有prop=revisions&rvprop=contentprop=revisions&rvprop=content&rvexpandtemplates=1的API查詢也大致做類似的工作,同時允許檢索一些附加信息。
狀態: MediaWiki的內置特性,在所有維基媒體服務器上均能使用。

一些維基百科服務器為大規模數據獲取配置了壓縮(gzip內容。這可以通過在HTTP請求頭裡加上一行"Accept-Encoding: gzip"來獲得。如果HTTP回報頭包含"Content-Encoding: gzip"就表明文檔是gzip格式的,否則為普通的未壓縮格式。注意這些特性僅僅是對於特定的服務器而配置的,並不是MediaWiki軟件的特性。其他部署MediaWiki的網站可能沒有此特性。

登入/建立新帳號

被認可的機器人需要登錄以作出編輯。儘管機器人可以在沒有登錄的情況下作出讀取請求,完成測試的機器人還是應該登錄以進行所有活動。登錄擁有機器人標籤的賬號的機器人可以在每次對Mediawiki API(api.php)請求時獲得更多結果。大多數機器人程序框架應該自動處理登錄以及Cookies,但是如果你沒有使用一個存在的框架,你需要進行以下步驟。

為了安全起見,登錄數據必須使用HTTP POST方式傳送。因為HTTP GET請求的參數在URL中很容易看見,通過GET登錄是禁止的。

為了使用MediaWiki API登錄一個機器人,需要兩個POST請求:

請求1

如果密碼正確,會返回一個「NeedToken」的結果和一個XML格式的「標記」參數,參見文檔mw:API:Login。其他輸出格式是可用的。它也會返回如下所示的HTTP Cookie。

請求2

其中TOKEN是上一步結果獲得的令牌。上一步請求獲得的HTTP cookies必須與第二個請求一起傳入。

BOTPASSWORD是使用Special:BotPasswords取得的密碼,而不是登入帳號取得的密碼。

一個成功的登錄嘗試會從維基媒體服務器得到幾個HTTP cookie。機器人必須正確處理這些cookies並且在每次請求時發送回去(在編輯時更加重要)。在中文維基百科裡會使用以下cookies:zhwikiUserIDzhwikiTokenzhwikiUserNamezhwikisession緩存在發送或確認編輯時需要,否則會返回一個錯誤信息

編輯;編輯令牌

在編輯維基百科的頁面時,需使用編輯令牌系統。這個令牌看上去像一個末尾有「+\」的長十六進制數,例如:

d41d8cd98f00b204e9800998ecf8427e+\

編輯令牌的作用是防止「編輯劫持」(這種情況下,編輯者無意點擊某鏈接就可能產生編輯操作)

編輯過程涉及到兩個HTTP請求。第一步請求一個編輯令牌,第二步把要編輯頁面的新內容和剛才獲得的編輯令牌放在一起進行POST請求。每次登錄後編輯令牌都不會改變,因此第一步每次登錄只需做一次。[來源請求]

要獲得一個編輯令牌,請按照下列步驟做:

  • 用以下參數向MediaWiki API (api.php)發出POST請求(參見 mw:API:Edit):
    • action=query
    • meta=tokens
    • type=csrf

    令牌一定會在返回值的csrftoken屬性中。

如果機器人獲取到的編輯令牌沒有上述的十六位字符串(如編輯令牌只有'+\'),則說明機器人很可能沒有成功登錄。這可能有多種原因:服務器端身份驗證失敗、連接斷開或超時、cookies存儲/返回錯誤。如果這不是因為機器人程序錯誤,再次登錄以刷新登錄緩存即可。機器人可以使用Assert Api來確認其已經登錄。

編輯衝突

當多人同時嘗試編輯一個頁面時會發生編輯衝突。幾乎每個機器人都會遇到各種各樣的編輯衝突,因此製作機器人時應當包括處理編輯衝突的機制。

使用Mediawiki API(api.php)的機器人在讀取頁面準備編輯前,應當重新獲取編輯令牌以及starttimestamp(開始時間戳)和上一個版本的時間戳。可以使用prop=info|revisions在一次查詢中同時獲取令牌和頁面的內容(example)。當提交編輯時,設置starttimestampbasetimestamp屬性,並檢查服務器回應是否有錯誤信息。更多的細節,請參見mw:API:Edit - Create&Edit pages

總的來說,如果一次編輯沒有完成,機器人應當在做新編輯前再次檢查頁面,以確定編輯仍然是正確的。進一步說,如果機器人重新檢查並提交編輯,它必須足夠小心以避免可能導致的無限循環甚至編輯戰

機器人製作過程概覽

實際上,撰寫機器人代碼只是製作維基百科機器人工作的一部分。機器人操作者應該大致仿照以下開發步驟以保證機器人遵循維基百科的機器人方針。違背方針的機器人無法得到審批,嚴重者甚至會被封禁。

維基百科機器人開發流程概覽

構思

細化

  • 精確地(可能用一種非常嚴格的方式)描述你要寫的軟件有什麼任務要做。你應該詳盡地提出它要做什麼事。嘗試和其他的編輯者討論這個提議,並基於其他人的反饋來進行改進。即使是一個很偉大的想法,也能通過綜合其他編輯者的想法而變得更好。
  • 在最基本的情況下,經過你細化之後的機器人必須符合下列標準:
  • 無害(機器人的編輯不能對維基百科的平穩運行造成破壞)
  • 有用(機器人能夠比人工編輯更有效率,提供有用的服務)
  • 不浪費服務器資源
  • 遵守模板:Bots

軟件架構

  • 想一想你要怎麼造這個機器人,用什麼樣的編程語言和工具。一般認為,使用軟件架構能確保讓軟件系統符合產品需求,並且能確保迎合未來的需求。一些編程語言比另一些更適合做某些任務,更多細節請參考#編程語言和開發庫

實現

實現(編碼)涉及到把設計和計劃轉變成代碼。這可能是軟件工程裡面最顯而易見的工作了,但是並沒必要成為最大的一部分工作。在實現階段,你需要做:

  • 給你的機器人建立一個用戶頁。機器人絕對不能使用你自己的賬號進行編輯。機器人需要它自己的賬號,有自己的用戶名和密碼。
  • 在機器人的用戶頁上加入相同信息。加上一個指向討論頁面的鏈接是個不錯的想法,大家可以對每一個功能提出贊成或者反對的意見。
  • 用你選擇的編程語言對機器人編寫代碼。

測試

測試你的機器人最好的方式是:讓它把要進行的更改寫在一個頁面上,而不是對維基進行實際的更改。有的機器人框架(比如Pywikipediabot)有一些現成的方法可以用來顯示差異。在申請期間,機器人很可能會有一個試用期(有一些編輯次數或者運行時間上的限制),在此期間讓它進行一些實際的編輯,便於對它進行微調、解決Bug。試用期結束的時候,如果一切都按照計劃進行,機器人就應該能被批准執行全功能的操作。

文檔

一個重要的(也是常常被忽視的)任務就是為機器人的內部設計撰寫文檔,這樣是為了便於將來的維護和增強。如果你允許複製你的機器人的話,這就尤其重要了。如果你想讓別人可以複製你的機器人,最理想的情況是在它的用戶頁上公布源代碼。為了便於使用,代碼應該有詳細的文檔說明(通常使用注釋)。

詢問和抱怨

你應該準備好在你的對話頁上回應對機器人的各種詢問或反對意見,尤其是在機器人在一個潛在的敏感區域進行操作(比如清理合理使用圖像)的情況下。

維護

為了解決發現的Bug,或者迎合新的需求,維護和改進機器人會比一開始開發的時候花費的時間多得多。不光是加入與原始設計不相符的代碼,僅僅就是確定軟件維護完成之後在某些點上怎麼工作,就需要很大的努力(這也是一直要為代碼寫文檔的一個原因)。

  • 如果你要對機器人在功能上做一個重大的修改,應該提出申請

運行機器人的一般準則

官方的機器人政策給出了開發機器人的時候應該考慮的一些主要問題。除此之外,還有一些更一般的問題應該考慮。

編寫機器人的最佳做法

  • 按照維基媒體用戶代理政策,為機器人設置一個用戶代理頭。如果不這樣做的話,機器人可能會遇到錯誤,最終可能會被技術人員在服務器級別進行屏蔽。
  • 使用5秒的最大延遲參數。這能讓機器人在服務器負載低的時候快速運行,在服務器負載高的時候暫停運行。
    • 如果編寫機器人使用的框架不支持最大延遲的話,請限制總請求數(包括讀寫請求),不要超過每秒10次。
  • 儘可能地使用API,把查詢頻率限制到服務器允許的最大值,把總請求數設置為足夠小的值。
  • 編輯(寫)請求比讀請求更耗費服務器時間。設計代碼的時候,把編輯操作控制到最少。
    • 儘量整合多次編輯。一次大編輯要好過十次小編輯。
  • 如果可以的話,在HTTP客戶端庫里啟用HTTP持久鏈接HTTP壓縮
  • 不要用多線程發出請求。等到一次請求完成之後再開始下一次請求。
  • 當從服務器收到錯誤信息的時候,使用二元指數後退演算法(Binary Exponential Backoff Algorithm) 進行延遲。像超時這樣的錯誤常常意味着服務器負載過重。在重複發出的請求之間採用遞增的時間延遲。
  • 使用斷言編輯擴展。這是一個專門為機器人設計的擴展,用來檢查特定的條件是否成立。這個擴展已經在維基百科上啟用了。
  • 在開始大型的自動化運行前,徹底測試好你的代碼。逐個考察試運行期間所有的編輯操作,確保完美。

應該考慮實現的常見機器人特徵

人工協助

如果機器人所做的工作需要根據上下文進行判斷或評價(例如改正拼寫錯誤),你應該考慮讓你的機器人可以人工協助。也就是說,別讓機器人的編輯沒有人工確認。

停用機器人

好的機器人應該可以在有必要的時候停用。請記住,如果你的機器人出錯了,你有責任對這些錯誤進行清理!你應該讓機器人在看到對話頁上留有特定信息的時候拒絕運行。這個信息可能是對它的活動抱怨的信息;這個可以用API meta=userinfo 查詢(這裡有個例子)。或者,你可以設置一個頁面,如果這個頁面的內容被改動,機器人就會停止運行(例如,機器人需要這個頁面是空的,僅僅有一個詞「True」或者其他什麼東西才能運行);可以在每次編輯之前載入這個頁面,檢查頁面的內容。

簽名

就像人一樣,如果機器人要編輯維基百科的討論頁,他也應該用四個波浪線(~~~~)留下簽名。請記住,簽名應該留在討論頁(talk命名空間)上,不要讓機器人在任何其他的頁面上簽名。

開源機器人

許多操作機器人的人選擇開放源代碼,在有些情況下,申請特定的複雜機器人之前可能會要求開源。開放你的代碼有幾個好處:

  • 允許別人再審查一下你的代碼,發現潛在的Bug。As with prose,對於代碼的作者來說,完全覆審代碼經常是件困難的事。
  • 別人可以使用你的代碼製作他們自己的機器人。可以讓一個剛開始寫機器人的用戶在寫機器人的時候,能拿你的代碼做例子或者模板。
  • 鼓勵更安全的做法,而不是「隱藏就是安全」(「security through obscurity」)。
  • 如果你離開這個項目了,允許其他用戶不用寫新代碼就可以運行你的機器人。

雖然開源代碼很少需要,有些情況下代碼也不應該公開(例如英文維基百科中,機器人ProcseeBot的開源代碼中含有尋找代理的代碼,就可以被其他網站用於惡意目的),但是維基百科鼓勵開源,因為維基百科要保持開放和透明的性質。

開放源代碼可能為編寫代碼帶來額外的工作。要確保把像密碼這樣的敏感信息分開保存在不公開的文件里。

開放源代碼有幾種不同的選擇。有的用戶可能選擇把代碼放在機器人用戶空間的一個子頁面上,雖然這樣會帶來維護上麻煩(如果不是自動的話),而且會使代碼在多個協議(維基百科的協議再加上你自己指定的協議)下發布。另一種解決方案是使用版本控制系統,比如SVNGitMercurial。英文維基百科上有兩個條目,一個是比較不同的版本控制系統之間的區別,另一個比較不同開源軟件託管設備間的區別(目前(2012年1月19日)中文維基百科也有一個條目對應後者:自由軟件主機服務比較),其中很多是免費的。維基媒體工具服務(Wikimedia Toolserver)也為用戶提供SVN託管服務

編程語言和開發庫

幾乎任何編程語言都可以編寫機器人。選擇什麼樣的語言常常取決於機器人編寫者的經驗(哪種語言比較熟悉),或者是哪種預先開發的庫更適合於完成所需的任務。下面列出了一些語言,它們有一些開發庫,用來協助完成機器人的任務。

Perl

Perl運行時編譯器。這就意味着不需要像其他語言那樣自己編譯每一次構建(Build)。相反,你只需要簡單地使用像Gvim這樣的文本編輯器就能創建程序。然後,把代碼交給解釋器執行。代碼不是位於你自己的電腦上,就是位於遠程電腦(Web服務器)上。如果位於Web服務器上,你可以通過CGI開始運行程序,啟動接口服務。Perl適用於大多數操作系統,包括Microsoft WindowsMac OS XUNIX/Linux。如果你的ISP提供給你Web空間,那麼這是個好機會,你可以在Web服務器上訪問、運行Perl程序。

Perl編程入門指南:

開發庫:

  • MediaWiki::API – 一個Perl模塊,基於MediaWiki API提供低級接口,允許檢索、編輯、上傳/下載文件。
  • MediaWiki::Bot – 一個相當完整的機器人架構,用Perl寫成。提供比MediaWiki::API更高級的抽象。插件可提供管理功能。
  • Anura – 使用libwww-perl的,到MediaWiki的Perl接口。不推薦使用,因為當前版本不會檢查編輯衝突。
  • WWW::Mediawiki::Client – Perl模塊和命令行客戶端。
  • WWW::Wikipedia – Perl模塊,提供維基百科接口。
  • Perl Wikipedia ToolKit – Perl模塊,解析維基格式文本,提取數據。
  • MediaWiki CPAN Package[失效連結] by Edward Chernenko – 豐富的API,但是也有幾個嚴重的Bug。
  • Mediawiki::API – 英文維基百科用戶CBM編寫的開發庫,具有強大的自動錯誤處理功能,包裝了許多常見的API.php使用方式。這個開發庫與CPAN上的開發庫不同。

PHP

PHP可以用於編寫機器人。如果你想對機器人提供基於Web表單的接口,那麼PHP是特別好的選擇(尤其是使用cURL拓展,可以實現基於HTTP/HTTPS的請求)。舉個例子,假如你想創建一個用於重命名分類的機器人,你可以創建一個HTML表單,把分類的當前和所需名稱填到表單裡。當表單提交的時候,機器人可以讀取這些輸入,然後編輯當前分類下的所有文章,把它們移動到所需的分類。(很顯然,使用表單接口的機器人與在Web上隨機衝浪的機器人相比,在某種程度上更加安全)

Python

Python是一種流行的解釋型面向對象語言。

Python入門:

開發庫:

Microsoft .NET

Microsoft .NET是一組編程語言,包括C#C++/CLIVisual Basic .NETJ#JScript .NETIronPython,和Windows PowerShell。經常使用的開發環境是Microsoft Visual Studio integrated development environment,或者是其免費版本Microsoft Visual Studio Express。.NET程序使用Mono Project,可以在LinuxUnixBSDSolarisMac OS X,以及Windows上運行。

入門:

Libraries:

Java

Java程序一般使用IDE開發,比如Eclipse;也可以使用命令行控制台開發(使用javac和其他Java程序)。

入門:

開發庫:

JavaScript

JavaScript是一種主要用於網頁的腳本語言。通過把JavaScript腳本添加到your vector.js或者your monobook.js,可以增強維基百科的功能。在某些情況下,JavaScript腳本也可能離線執行。

開發庫:

  • 英文維基百科上的機器人Luasóg bot是一個JavaScript框架,可用於標準的請求(例如登錄、退出、讀取、編輯等等),也有對MediaWiki API的一般包裝方法,還包含了像節流這樣那個的有用的東西。這個項目包含了一個低級的IDE,可用於離線開發和執行。
  • Cewbot 採用了包含製作機器人功能的 JavaScript 軟體架構,可離線開發和運行。
framework: wikiapi / CeJS MediaWiki 自動化作業用的程式庫
可執行環境: node.js, JScript
採用 CeJS 函式庫來製作維基百科機器人的範例

Ruby

開發庫:

  • MediaWiki::Gateway – API的Ruby框架。已積極地維護、測試到了MediaWiki 1.16,與維基媒體的諸站點兼容。
  • rbmediawiki – 用Ruby編寫機器人的框架,使用MediaWiki的API。作者是英文維基百科用戶Ignacio Icke

Chicken Scheme

Iron Chicken是Chicken Scheme的擴展,使Mediawiki API可以用S-表達式編寫,提供API和SXML格式的HTML輸出,可以很容易地查詢。

示例:獲取一個分類的成員,寫入一個客戶端用戶的用戶空間頁面:

開發庫:

Common Lisp

  • cl-mediawiki是實現了MediaWikiAPI的Common Lisp包。使用JSON作為查詢數據格式。支持最大延遲和斷言編輯擴展。

Haskell

Tcl

C++/Qt4.5

  • [1](俄文) – 簡單的維基媒體機器人,用C++/Qt寫成,只有很少的功能,像認證、獲取頁面源碼、提交頁面源碼。