Skip to content

Instantly share code, notes, and snippets.

@justindujardin
Last active September 4, 2015 14:45
Show Gist options
  • Save justindujardin/b6bcee92af030f618bdd to your computer and use it in GitHub Desktop.
Save justindujardin/b6bcee92af030f618bdd to your computer and use it in GitHub Desktop.
Use LINQ to parse image query results from Google, Bing, and Yahoo search engines.
namespace SilverShorts
{
/// <summary>
/// Implement a Microsoft Bing IImageQuery provider
/// </summary>
public class BingImageQuery : IImageQuery
{
/// <summary>
/// Bing Image Query requires a valid ApiKey
/// See: http://www.bing.com/developer/
/// </summary>
public bool RequiresApiKey { get { return true; } }
public string FormatQueryUrl(string search, string appId, int numImages, int offset, bool useSafeSearch)
{
return "http://api.bing.net/xml.aspx?"
+ "AppId=" + appId
+ "&Query=" + search
+ "&Sources=Image"
+ "&Version=2.0"
+ "&Market=en-us"
+ (useSafeSearch ? "&Adult=Moderate" : "")
+ "&Image.Count=" + numImages.ToString()
+ "&Image.Offset=" + offset.ToString();
}
public void ProcessResultString(string response, List<ImageResult> results)
{
// Parse the XML response text
XDocument doc = XDocument.Parse(response);
// Elements in the response all conform to this schema and have a namespace prefix of mms:
// For our LINQ query to work properly, we must use mmsNs + ElementName
XNamespace mmsNs = XNamespace.Get("http://schemas.microsoft.com/LiveSearch/2008/04/XML/multimedia");
// Build a LINQ query to parse the XML data into our custom ImageResult objects
var imageResults =
from ir in doc.Descendants()
where ir.Name.Equals(mmsNs + "ImageResult")
select new ImageResult()
{
Title = ir.Element(mmsNs + "Title").Value,
MediaUrl = ir.Element(mmsNs + "MediaUrl").Value,
Url = ir.Element(mmsNs + "Url").Value,
DisplayUrl = ir.Element(mmsNs + "DisplayUrl").Value,
Width = Int32.Parse(ir.Element(mmsNs + "Width").Value),
Height = Int32.Parse(ir.Element(mmsNs + "Height").Value),
Thumb =
(from th in ir.Descendants()
where th.Name.Equals(mmsNs + "Thumbnail")
select new ImageResult.Thumbnail()
{
Url = th.Element(mmsNs + "Url").Value,
Width = Int32.Parse(th.Element(mmsNs + "Width").Value),
Height = Int32.Parse(th.Element(mmsNs + "Height").Value),
}).Single(),
};
// Execute the LINQ query and stuff the results into our list
results.AddRange(imageResults);
}
}
}
namespace SilverShorts
{
/// <summary>
/// Implement a Google IImageQuery provider using AJAX api and JSON.Net
/// See: http://code.google.com/apis/ajaxsearch/documentation/reference.html#_intro_fonje
/// </summary>
public class GoogleImageQuery : IImageQuery
{
/// <summary>
/// Google Image Query does not require (but strongly recommends) a valid ApiKey
/// </summary>
public bool RequiresApiKey { get { return false; } }
public string FormatQueryUrl(string search, string appId, int numImages, int offset, bool useSafeSearch)
{
return "http://ajax.googleapis.com/ajax/services/search/images?v=1.0"
+ "&q=" + search
+ "&key=" + appId
+ (useSafeSearch ? "&safe=m" : "")
+ "&start=" + Convert.ToString(offset);
}
public void ProcessResultString(string response, List<ImageResult> results)
{
// Parse the JSON string
JObject json = JObject.Parse(response);
// Check response validity, throw exception with details if error
if ((int)json["responseStatus"] != 200)
throw new Exception((string)json["responseDetails"]);
// Parse out results using LINQ
var imageResults =
from ir in json["responseData"]["results"].Children()
where ((string)ir["GsearchResultClass"]).Equals("GimageSearch")
select new ImageResult()
{
Title = (string)ir["title"],
MediaUrl = (string)ir["unescapedUrl"],
Url = (string)ir["url"],
DisplayUrl = (string)ir["visibleUrl"],
Width = Int32.Parse((string)ir["width"]),
Height = Int32.Parse((string)ir["height"]),
Thumb = new ImageResult.Thumbnail()
{
Url = (string)ir["tbUrl"],
Width = Int32.Parse((string)ir["tbWidth"]),
Height = Int32.Parse((string)ir["tbHeight"]),
}
};
// Execute the LINQ query and stuff the results into our list
results.AddRange(imageResults);
}
}
}
namespace SilverShorts
{
public class WebImageQuery
{
/// <summary>
/// Construct a WebImageQuery using the specified IImageQuery provider
/// </summary>
public WebImageQuery(IImageQuery provider) { _queryProvider = provider; }
private WebImageQuery() { }
private IImageQuery _queryProvider;
/// <summary>
/// Specifies the API specific key (if any) for the search provider
/// </summary>
private string _apiKey;
public string ApiKey
{
get { return _apiKey; }
set { _apiKey = value; }
}
/// <summary>
/// Delegate for Completed query event handlers
/// </summary>
/// <param name="results"></param>
public delegate void QueryCompletedEventHandler(List<ImageResult> results);
/// <summary>
/// Fired when the asynchronous web image query is complete
/// </summary>
public event QueryCompletedEventHandler QueryCompleted;
/// <summary>
///
/// </summary>
/// <param name="search"></param>
/// <param name="callback"></param>
/// <param name="numImages"></param>
/// <param name="offset"></param>
/// <param name="useSafeSearch"></param>
public void Search(string search, int numImages = 10, int offset = 0, bool useSafeSearch = true)
{
if (_queryProvider == null)
throw new ArgumentNullException("_queryProvider");
if (_queryProvider.RequiresApiKey && string.IsNullOrEmpty(_apiKey))
throw new ArgumentNullException("ApiKey", "This search provider requires a valid key");
string requestString = _queryProvider.FormatQueryUrl(search, _apiKey,numImages, offset, useSafeSearch);
WebClient client = new WebClient();
client.DownloadStringCompleted += _downloadStringCompleted;
client.DownloadStringAsync(new Uri(requestString, UriKind.Absolute));
}
/// <summary>
/// WebClient DownloadStringAsync Event handler
/// </summary>
/// <param name="e">e.UserState as SearchResultCallback</param>
private void _downloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (_queryProvider == null)
throw new ArgumentNullException("_queryProvider");
if (e.Error != null)
return;
List<ImageResult> results = new List<ImageResult>();
try
{
_queryProvider.ProcessResultString(e.Result.ToString(), results);
}
catch (System.Exception ex)
{
throw new Exception("Failed Process Image Query Result", ex);
}
// QueryCompleted event
if (QueryCompleted != null)
QueryCompleted(results);
}
}
}
namespace SilverShorts
{
/// <summary>
/// Implement a Yahoo Image Search IImageQuery provider
/// </summary>
public class YahooImageQuery : IImageQuery
{
/// <summary>
/// Yahoo Image Query requires a valid ApiKey
/// See: https://developer.apps.yahoo.com/projects
/// </summary>
public bool RequiresApiKey { get { return true; } }
public string FormatQueryUrl(string search, string apiKey, int numImages, int offset, bool useSafeSearch)
{
return "http://search.yahooapis.com/ImageSearchService/V1/imageSearch?"
+ "appid=" + apiKey
+ "&query=" + search
+ "&results=" + numImages
+ "&start=" + offset
+ (useSafeSearch ? "" : "&adult_ok=1");
}
public void ProcessResultString(string response, List<ImageResult> results)
{
// Parse the XML response text
XDocument doc = XDocument.Parse(response);
XNamespace yahNs = "urn:yahoo:srchmi";
// Build a LINQ query to parse the XML data into our custom ImageResult objects
var imageResults =
from ir in doc.Descendants()
where ir.Name.Equals(yahNs + "Result")
select new ImageResult()
{
Title = ir.Element(yahNs + "Title").Value,
MediaUrl = ir.Element(yahNs + "ClickUrl").Value,
Url = ir.Element(yahNs + "Url").Value,
DisplayUrl = ir.Element(yahNs + "RefererUrl").Value,
Width = Int32.Parse(ir.Element(yahNs + "Width").Value),
Height = Int32.Parse(ir.Element(yahNs + "Height").Value),
Thumb =
(from th in ir.Descendants()
where th.Name.Equals(yahNs + "Thumbnail")
select new ImageResult.Thumbnail()
{
Url = th.Element(yahNs + "Url").Value,
Width = Int32.Parse(th.Element(yahNs + "Width").Value),
Height = Int32.Parse(th.Element(yahNs + "Height").Value),
}).Single(),
};
// Execute the LINQ query and stuff the results into our list
results.AddRange(imageResults);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment