ClickAider

Ruby Wrapper for MSN Live Search API

After a couple painful hours of trial and error, I’d like to share some code that simplifies the process of accessing the MSN Live Search API from Ruby

The code assumes that you have auto-generated the SOAP driver for the MSN Search web services in a directory called msn_search_driver, using the following command.

wsdl2ruby –wsdl http://soap.search.msn.com/webservices.asmx?wsdl –type client

msn_search.rb takes care of the nasty details for you, so that you can write simple code like this:

require 'msn_search'
MsnSearch.new.search("bogle").results.each {|r| puts r.url}

<RANT>
Although it’s possible in to call the SOAP driver directly, the API is hard to use because of complex, nested request and response types, poorly documented mandatory arguments, and unhelpful error messages on invalid requests. (These shortcomings are not unique to the MSN SOAP interface– I’ve experience similar shortcomings in many other SOAP apis. REST-based APIs tend to win hands down in terms of simplicity and debuggability.  

Note that neither Google, Yahoo, nor MSN will allow to fetch beyond the first 1000 results in a search, independent of their daily hit limits. If you need to use a web index for an application that’s more than a toy, you’re probably much better off using something like Alexa Web Search Platform than any of the major search APIs. The downside to the Alexa platform is that C and Java are the only supported languages.   The Alexa platform supports C, Java, and Ruby.  Alexa provides Ruby-based tutorial on how to build an image search application using their index.
</RANT>

Now that I’ve got that rant off my chest, here’s the code.


msn_search.rb
($:).push('msn_search_driver')

require ‘defaultDriver.rb’

class MsnSearch
	attr_accessor :driver

	def initialize(appID = ‘INSERT_YOUR_APP_ID_HERE’)
		@driver = MSNSearchPortType.new
		@appID = appID
	end

	def search(query, offset=0, count=50, source=”Web”,
safeSearch=”Off”, culture=”en-US”)
		s = Search.new
		s.request = with_new(SearchRequest) do |r|
			r.cultureInfo = culture
			r.safeSearch = safeSearch
			r.query = query
			r.appID = @appID
			r.requests = source_requests =
ArrayOfSourceRequestRequests.new
			source_requests << with_new(SourceRequest) do |sr|
				sr.offset = offset
				sr.count = count
				sr.source = source
				sr.resultFields = “All”
			end
		end
		@driver.search(s).response.responses.sourceResponse
	end

	def set_debug_mode(dev = STDOUT)
		@driver.wiredump_dev = dev
	end

protected
	def with_new(klass)
		instance = klass.new
		yield instance
		return instance
	end

end


2 Comments so far
Leave a comment

Phil,

what is the Search object you refer to in :
s = Search.new ?

Werner

That’s a class generated by wsdl2ruby –wsdl http://soap.search.msn.com/webservices.asmx?wsdl –type client


Leave a comment

(required)

(required)