維基百科:製作機械人

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

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

為何需要機械人?

機械人以比人類快得多的速度執行任務。如果你需要完成一些簡單但冗長的工作(比如當你需要添加模板到某個類別的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寫成,只有很少的功能,像認證、取得頁面原始碼、提交頁面原始碼。