The Road to Delphi

Delphi – Free Pascal – Oxygene

Using the Bing search API (Windows Azure Marketplace version) from Delphi

2 Comments

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.

Recommended Resources

Author: Rodrigo

Just another Delphi guy.

2 thoughts on “Using the Bing search API (Windows Azure Marketplace version) from Delphi

  1. Pingback: Using the Bing search API from Delphi « The Road to Delphi – a Blog about programming

  2. 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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s