Last active
September 4, 2015 14:45
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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