用 Delphi 呼叫 Google 的 Search Engine |
|
Diviner
初階會員 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
用 Delphi 呼叫 Google 的 Search Engine: Delphi 能讓開發者以 SOAP 技術進行遠端呼叫, 我希望透過例子讓各位朋友一同向這方向研究研究。最近 Google Search Engine 提供了一組 Web Services, 讓用戶透過 SOAP 呼叫其網上搜尋服務, 也就是說, 我們可以替自己開發的程式, 加一個網上搜尋功能進去, 其搜尋的強度, 就是 Google 搜尋的強度, 因為盡管表面上是我們的程式介面讓用戶輸入搜尋條件, 實則背後是 Google 替我們進行搜尋, 然後把搜尋結果傳回給我們的程式而已。Google 是一個我很喜歡用的 Search Engine, 所以我很喜歡這個範例, 希望你也同樣喜歡。 首先第一個步驟是到 Google 拿到這個呼叫服務的 Google Web APIs Developer's Kit, 網址是 http://www.google.com/apis/ , 這個 Kit 的大小只有 642k, 不算大, 下載回來吧。 第二步是登記一個帳號, 只有申請到這個帳號, Google 才讓你呼叫她的搜尋服務, 這也很合理的, 她要控制資源。免費的帳號, 每天只會讓你搜尋 1000 次, 應該也夠玩吧, 收費的帳號就沒細究了。申請帳號不複雜, 都像是申請其他網上資源一樣, 先給你確認信, 確認信中有個 HyperLink, 按下確認後 Google 會寄給你第二封信, 告知你帳號申請成功, 並在信中附上一個 License Key (這個 Key 看起來像這樣的字串: "o2/Xx4mvQCafLDZ y90hA2Qso9PxSHkN"), 這個 License Key 是稍後在 SOAP 進行遠端呼叫時, 放在呼叫函數中作為參數傳遞給 Google, 然後呼叫才會通過的。 在 Delphi 中作 SOAP 遠端呼叫, 我使用了 Early Binding, 也就是一種編譯時期已可很大程度上確定呼叫句法沒有出錯的方法, 例如呼叫函數名稱出錯, 參數的資料型別的出錯等, 都在 Compile 時被指正, 且執行速度也是比較快的方法。相對於 Late Binding 而言, Late Binding 雖然執行速度較慢, 及要小心 Run Time Error 之外, 寫法卻又比較簡潔, 是為各有利弊; 而且, 目前 Delphi 要使用 SOAP 進行 Late Binding 的 SOAP 呼叫, 是要借助 MS SOAP Kit 的, 這個我還未試過, 有經驗的朋友, 也請在這裡分享一下經驗。 言歸正傳, Delphi 進行 Early Binding 時需要一個 Interface, 讓 Delphi 編譯時作為依據, 通常這個 Interface 會獨立放在一個 Unit 中, 可是目前我們連怎樣呼叫 Google 的服務都不知道, 又如何替她寫一個 Interface 呢? 我們怎麼知道 Google 提供的呼叫函式叫甚麼名稱呢? 函式需要甚麼參數呢? 傳回怎麼樣的資料呢? 不用擔心, 這些資料, SOAP 是以一個 WSDL 文件來描述的, Google 會提供這個文件給你, 讓你及 Delphi 懂得呼叫其服務。 WSDL (Web Service Definition Language) 是個 XML 格式的文件, Delphi 有一個工具能把這個 XML 格式的文件轉換成 Pascal 格式, 好讓你進行前面所說的 Early Binding, 這個工具便做 Web Service Importer Wizard。我們如何從 Google 取得這個文件呢? 這個文件在其 Development's Kit 中, 叫做 "GoogleSearch.wsdl", 不過我還是建議你直接到 Google 去拿, 因為說不定 Google 有新版本的 WSDL 文件。根據 Google 提供的資料, 她把 WSDL 文件放在 http://api.google.com/GoogleSearch.wsdl。 材料算是齊了, 現在到 Delphi 6 出場了。開個新 Project, 畫面的設計先不說, 我們先用 Web Service Importer Wizard 把 Pascal 格式的 Interface 轉換出來。按 File/New/Other, 選 WebServices 頁中的 WSDL Importer, 在其 WSDL Source 框中的 Location of WSDL File or URL 中填上 http://api.google.com/GoogleSearch.wsdl, 按 Next, 再按 Finish, Importer 便會將 WSDL 文件轉換為 Pascal 格式 Unit, 並自動加進目前的 Project 中了, Unit 名稱應該叫做 GoogleSearch, 請在 Form 中 uses 這個 Unit, 以進行 Early binding。 接著在本程式的 Form 上放一個 THTTPRIO Component (Component 放在 WebServices Component Palette 中), 用以連接 Google Web Service。在 Object Inspector 中設定其 WSDLLocation 屬性為 http://api.google.com/GoogleSearch.wsdl (不用逐字鍵入, 一選便選得出來, 這就是 Early Binding 的優點), 接著設定 Service 屬性為 GoogleSearchService, Port 屬性設定為 GoogleSearchPort, 我把這個 THTTPRIO Component 命名為 wsGoogleSearch。 接下來, 我替程式設計了一個 Keyword 輸入欄, 搜尋鍵, 及兩個搜尋結果輸出盒, 就不慢慢描述了, 乾脆把 Form 的 source code 貼出來, 你應該不難看得明。
//************************************************************* unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Rio, SOAPHTTPClient, StdCtrls, ComCtrls, GoogleSearch; type TForm1 = class(TForm) wsGoogleSearch: THTTPRIO; btnSearch: TButton; lvResultItem: TListView; lvResult: TListView; Edit1: TEdit; procedure btnSearchClick(Sender: TObject); procedure lvResultChange(Sender: TObject; Item: TListItem; Change: TItemChange); private SearchResult: GoogleSearchResult; procedure ShowResultItem(const item: ResultElement); { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.btnSearchClick(Sender: TObject); procedure ShowResult(const res: GoogleSearchResult); procedure AddLine(const c1, c2: String); var item: TListItem; begin item := lvResult.Items.Add; item.Caption := c1; item.SubItems.Add(c2); end; var i: Integer; begin lvResult.Clear; for i := 0 to length(res.resultElements) - 1 do begin AddLine(res.resultElements[i].title, res.resultElements[i].URL); end; end; var key, q, restrict, lr, ie, oe: String; start, maxResults: Integer; filter, safeSearch: Boolean; begin key := 'o2/Xx4mvQCafLDZ y90hA2Qso9PxSHkN'; q := Edit1.Text; start := 0; maxResults := 9; filter := true; restrict := 'countryTW'; safeSearch := false; lr := 'lang_zh-TW'; // 英文:'lang_en', 繁體中文:'lang_zh-TW', 簡體中文:'lang_zh-CN' ie := 'utf8'; // 英文:'latin1', 繁體中文:'big5', 簡體中文:'gb', 多語言: 'utf8' oe := 'utf8'; // 英文:'latin1', 繁體中文:'big5', 簡體中文:'gb', 多語言: 'utf8' btnSearch.Enabled := False; SearchResult := (wsGoogleSearch as GoogleSearchPort).doGoogleSearch (key, q, start, maxResults, filter, restrict, safeSearch, lr, ie, oe); btnSearch.Enabled := True; ShowResult(SearchResult); end; procedure TForm1.ShowResultItem(const item: ResultElement); procedure AddLine(const c1, c2: String); var item: TListItem; begin item := lvResultItem.Items.Add; item.Caption := c1; item.SubItems.Add(c2); end; begin lvResultItem.Clear; AddLine('Summary', item.summary); AddLine('URL', item.URL); AddLine('Snippet', item.snippet); AddLine('Title', item.title); AddLine('Host Name', item.hostName); AddLine('Director Category(full viawable name)', item.directoryCategory.fullViewableName); AddLine('Director Category(special encoding)', item.directoryCategory.specialEncoding); AddLine('Directory Title', item.directoryTitle); AddLine('Class Name', item.ClassName); end; procedure TForm1.lvResultChange(Sender: TObject; Item: TListItem; Change: TItemChange); begin if lvResult.ItemIndex <> -1 then ShowResultItem(SearchResult.resultElements[lvResult.ItemIndex]); end; end. //*************************************************************得某網友(忘了名稱, 又被駭客刪掉了文章)指正, 用 UTF8 作多語系搜尋, 便能成功使用中文作關鍵字作搜尋, 謝謝。 (mailto:diviner@i-cable.com)。 上文如有錯誤, 或有甚麼建議, 也請通知一下, 謝謝。 作者: 陳柱民 發表人 - diviner 於 2002/05/29 01:28:34 發表人 - diviner 於 2002/05/29 23:40:39
------
-- 小卜子 |
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
|
andersonhsieh
版主 發表:33 回覆:531 積分:439 註冊:2002-06-10 發送簡訊給我 |
|
design
一般會員 發表:0 回覆:1 積分:0 註冊:2002-06-20 發送簡訊給我 |
|
vv
一般會員 發表:0 回覆:3 積分:0 註冊:2002-03-13 發送簡訊給我 |
|
chfamy
中階會員 發表:87 回覆:161 積分:54 註冊:2002-05-03 發送簡訊給我 |
|
alanfujitsu
一般會員 發表:5 回覆:9 積分:2 註冊:2004-02-03 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |