Introduction
Some time ago I wrote a entry about how use the Bing search API from Delphi , now this API was migrated to the Windows Azure Marketplace so it’s time to upgrade the source code to access this API.
The Bing Search API allow you to get search results retrieving the results in XML or JSON format. This API offers multiple source types (or types of search results) with each query. For example you can request web, images, news, and video results for a single search query.
In order to use the Bing Search API you must obtain an account key in the Windows Azure Marketplace, Then this key must be used in a Basic Authentication scheme to authenticate the requests.
Building the URL
The next step is build a valid URL to make the GET request. This is the basic structure of a Bing Search URL.
https://api.datamarket.azure.com/Bing/Search/%5Bsourcetype%5D?Query=%5BSearchTerm%5D&$format=%5BResponse format]&$top=5&$skip=0
This sample URL which uses the Web source type.
https://api.datamarket.azure.com/Bing/Search/Web?Query=%27Delphi%27&$format=ATOM&$top=5&$skip=0
These are the URI Input parameters for the Web source type.
| Name | Sample values | Type | Required |
|---|---|---|---|
| Query | Hello | String | X |
| Adult | Moderate | String | |
| Latitude | 48.59 | Double | |
| Longitude | -112.31 | Double | |
| Market | en-US | String | |
| Options | EnableHighlighting | String | |
| WebFileType | XLS | String | |
| WebSearchOptions | DisableQueryAlterations | String |
These are the fields returned in the response.
| Name | Type |
|---|---|
| ID | Guid |
| Title | String |
| Description | String |
| DisplayUrl | String |
| Url | String |
Indy Sample
Check this sample Delphi code which uses Indy to make the GET request.
{$APPTYPE CONSOLE}
{$R *.res}
uses
MSXML,
ActiveX,
ComObj,
Variants,
IdURI,
IdHttp,
IdSSLOpenSSL,
SysUtils;
procedure GetBingInfoXML_Web(const SearchKey : string;Top, Skip : Integer);
const
ApplicationID= 'put your key here';
URI='https://api.datamarket.azure.com/Bing/Search/Web?Query=%s&$format=ATOM&$top=%d&$skip=%d';
var
XMLDOMDocument : IXMLDOMDocument;
XMLDOMNode : IXMLDOMNode;
cXMLDOMNode : IXMLDOMNode;
XMLDOMNodeList : IXMLDOMNodeList;
LIdHTTP : TIdHTTP;
LIOHandler : TIdSSLIOHandlerSocketOpenSSL;
LIndex : Integer;
Response: string;
begin
LIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
LIOHandler.SSLOptions.Method := sslvTLSv1;
LIOHandler.SSLOptions.Mode := sslmUnassigned;
LIOHandler.SSLOptions.VerifyMode := [];
LIOHandler.SSLOptions.VerifyDepth := 0;
LIOHandler.host := '';
LIdHTTP:= TIdHTTP.Create(nil);
try
LIdHTTP.Request.ContentEncoding := 'utf-8';
LIdHTTP.Request.BasicAuthentication:= True;
LIdHTTP.Request.Username:=ApplicationID;
LIdHTTP.Request.Password:=ApplicationID;
LIdHTTP.IOHandler:= LIOHandler;
Response:=LIdHTTP.Get(Format(URI,[TIdURI.PathEncode(QuotedStr(SearchKey)), Top, Skip]));
XMLDOMDocument:=CoDOMDocument.Create;
try
XMLDOMDocument.loadXML(Response);
XMLDOMNode := XMLDOMDocument.selectSingleNode('/feed');
XMLDOMNodeList := XMLDOMNode.selectNodes('//entry');
if XMLDOMNodeList<>nil then
for LIndex:=0 to XMLDOMNodeList.length-1 do
begin
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:ID',[LIndex]));
Writeln(Format('id %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:Title',[LIndex]));
Writeln(Format('Title %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:Description',[LIndex]));
Writeln(Format('Description %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:DisplayUrl',[LIndex]));
Writeln(Format('DisplayUrl %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:Url',[LIndex]));
Writeln(Format('Url %s',[String(cXMLDOMNode.Text)]));
Writeln;
end;
finally
XMLDOMDocument:=nil;
end;
finally
LIdHTTP.Free;
end;
finally
LIOHandler.Free;
end;
end;
begin
try
CoInitialize(nil);
try
GetBingInfoXML_Web('delphi programming blogs', 5, 0);
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
IXMLHTTPRequest Sample
Check this sample Delphi code which uses the IXMLHTTPRequest interface to make the GET request.
{$APPTYPE CONSOLE}
{$R *.res}
uses
MSXML,
ActiveX,
ComObj,
Variants,
IdURI,
SysUtils;
procedure GetBingInfoXML_Web(const SearchKey : string;Top, Skip : Integer);
const
ApplicationID= 'put your key here';
URI='https://api.datamarket.azure.com/Bing/Search/Web?Query=%s&$format=ATOM&$top=%d&$skip=%d';
COMPLETED=4;
OK =200;
var
XMLHTTPRequest : IXMLHTTPRequest;
XMLDOMDocument : IXMLDOMDocument;
XMLDOMNode : IXMLDOMNode;
cXMLDOMNode : IXMLDOMNode;
XMLDOMNodeList : IXMLDOMNodeList;
LIndex : Integer;
begin
XMLHTTPRequest := CreateOleObject('MSXML2.XMLHTTP') As IXMLHTTPRequest;
XMLHTTPRequest.open('GET',Format(URI,[TIdURI.PathEncode(QuotedStr(SearchKey)), Top, Skip]), False, ApplicationID, ApplicationID);
XMLHTTPRequest.send('');
if (XMLHTTPRequest.readyState = COMPLETED) and (XMLHTTPRequest.status = OK) then
begin
XMLDOMDocument:=CoDOMDocument.Create;
try
XMLDOMDocument.loadXML(XMLHTTPRequest.responseText);
XMLDOMNode := XMLDOMDocument.selectSingleNode('/feed');
XMLDOMNodeList := XMLDOMNode.selectNodes('//entry');
if XMLDOMNodeList<>nil then
for LIndex:=0 to XMLDOMNodeList.length-1 do
begin
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:ID',[LIndex]));
Writeln(Format('id %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:Title',[LIndex]));
Writeln(Format('Title %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:Description',[LIndex]));
Writeln(Format('Description %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:DisplayUrl',[LIndex]));
Writeln(Format('DisplayUrl %s',[String(cXMLDOMNode.Text)]));
cXMLDOMNode:=XMLDOMNode.selectSingleNode(Format('//entry[%d]/content/m:properties/d:Url',[LIndex]));
Writeln(Format('Url %s',[String(cXMLDOMNode.Text)]));
Writeln;
end;
finally
XMLDOMDocument:=nil;
end;
end;
end;
begin
try
CoInitialize(nil);
try
GetBingInfoXML_Web('delphi programming blogs', 5, 0);
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Pingback: Using the Bing search API from Delphi « The Road to Delphi – a Blog about programming
June 14, 2013 at 4:16 pm
Your Indy Sample has unicode issue. I fixed it by getting response into stream created with Encoding.UTF8. I am not an expert for Indy but the reason might be empty response encoding.